summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am29
-rw-r--r--src/Makefile.in577
-rw-r--r--src/base64.c103
-rw-r--r--src/dom.c181
-rw-r--r--src/filter.c181
-rw-r--r--src/iks.c762
-rw-r--r--src/ikstack.c202
-rw-r--r--src/io-posix.c137
-rw-r--r--src/jabber.c330
-rw-r--r--src/md5.c189
-rw-r--r--src/sax.c634
-rw-r--r--src/sha.c152
-rw-r--r--src/stream.c642
-rw-r--r--src/utility.c180
14 files changed, 4299 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..20ca263
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,29 @@
+##
+## Process this file with automake to produce Makefile.in
+##
+
+INCLUDES = -I$(top_srcdir)/include
+
+lib_LTLIBRARIES = libiksemel.la
+
+if DO_POSIX
+posix_c = io-posix.c
+endif
+
+libiksemel_la_SOURCES = \
+ ikstack.c \
+ utility.c \
+ iks.c \
+ sax.c \
+ dom.c \
+ $(posix_c) \
+ stream.c \
+ sha.c \
+ jabber.c \
+ filter.c \
+ md5.c \
+ base64.c
+
+libiksemel_la_LDFLAGS = -version-info 4:0:1 -no-undefined
+libiksemel_la_CFLAGS = $(CFLAGS) $(LIBGNUTLS_CFLAGS)
+libiksemel_la_LIBADD = $(LIBGNUTLS_LIBS)
diff --git a/src/Makefile.in b/src/Makefile.in
new file mode 100644
index 0000000..3b2093c
--- /dev/null
+++ b/src/Makefile.in
@@ -0,0 +1,577 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005 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@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+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 = src
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/include/config.h
+CONFIG_CLEAN_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 = `echo $$p | sed -e 's|^.*/||'`;
+am__installdirs = "$(DESTDIR)$(libdir)"
+libLTLIBRARIES_INSTALL = $(INSTALL)
+LTLIBRARIES = $(lib_LTLIBRARIES)
+am__DEPENDENCIES_1 =
+libiksemel_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+am__libiksemel_la_SOURCES_DIST = ikstack.c utility.c iks.c sax.c dom.c \
+ io-posix.c stream.c sha.c jabber.c filter.c md5.c base64.c
+@DO_POSIX_TRUE@am__objects_1 = libiksemel_la-io-posix.lo
+am_libiksemel_la_OBJECTS = libiksemel_la-ikstack.lo \
+ libiksemel_la-utility.lo libiksemel_la-iks.lo \
+ libiksemel_la-sax.lo libiksemel_la-dom.lo $(am__objects_1) \
+ libiksemel_la-stream.lo libiksemel_la-sha.lo \
+ libiksemel_la-jabber.lo libiksemel_la-filter.lo \
+ libiksemel_la-md5.lo libiksemel_la-base64.lo
+libiksemel_la_OBJECTS = $(am_libiksemel_la_OBJECTS)
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/include
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(libiksemel_la_SOURCES)
+DIST_SOURCES = $(am__libiksemel_la_SOURCES_DIST)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DO_POSIX_FALSE = @DO_POSIX_FALSE@
+DO_POSIX_TRUE = @DO_POSIX_TRUE@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LDFLAGS = @LDFLAGS@
+LIBGNUTLS_CFLAGS = @LIBGNUTLS_CFLAGS@
+LIBGNUTLS_CONFIG = @LIBGNUTLS_CONFIG@
+LIBGNUTLS_LIBS = @LIBGNUTLS_LIBS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_OBJDUMP = @ac_ct_OBJDUMP@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+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@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+INCLUDES = -I$(top_srcdir)/include
+lib_LTLIBRARIES = libiksemel.la
+@DO_POSIX_TRUE@posix_c = io-posix.c
+libiksemel_la_SOURCES = \
+ ikstack.c \
+ utility.c \
+ iks.c \
+ sax.c \
+ dom.c \
+ $(posix_c) \
+ stream.c \
+ sha.c \
+ jabber.c \
+ filter.c \
+ md5.c \
+ base64.c
+
+libiksemel_la_LDFLAGS = -version-info 4:0:1 -no-undefined
+libiksemel_la_CFLAGS = $(CFLAGS) $(LIBGNUTLS_CFLAGS)
+libiksemel_la_LIBADD = $(LIBGNUTLS_LIBS)
+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 \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
+ 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_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
+install-libLTLIBRARIES: $(lib_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ test -z "$(libdir)" || $(mkdir_p) "$(DESTDIR)$(libdir)"
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ if test -f $$p; then \
+ f=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) '$$p' '$(DESTDIR)$(libdir)/$$f'"; \
+ $(LIBTOOL) --mode=install $(libLTLIBRARIES_INSTALL) $(INSTALL_STRIP_FLAG) "$$p" "$(DESTDIR)$(libdir)/$$f"; \
+ else :; fi; \
+ done
+
+uninstall-libLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @set -x; list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ p=$(am__strip_dir) \
+ echo " $(LIBTOOL) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$p'"; \
+ $(LIBTOOL) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$p"; \
+ done
+
+clean-libLTLIBRARIES:
+ -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES)
+ @list='$(lib_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libiksemel.la: $(libiksemel_la_OBJECTS) $(libiksemel_la_DEPENDENCIES)
+ $(LINK) -rpath $(libdir) $(libiksemel_la_LDFLAGS) $(libiksemel_la_OBJECTS) $(libiksemel_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libiksemel_la-base64.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libiksemel_la-dom.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libiksemel_la-filter.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libiksemel_la-iks.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libiksemel_la-ikstack.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libiksemel_la-io-posix.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libiksemel_la-jabber.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libiksemel_la-md5.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libiksemel_la-sax.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libiksemel_la-sha.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libiksemel_la-stream.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libiksemel_la-utility.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+libiksemel_la-ikstack.lo: ikstack.c
+@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libiksemel_la_CFLAGS) $(CFLAGS) -MT libiksemel_la-ikstack.lo -MD -MP -MF "$(DEPDIR)/libiksemel_la-ikstack.Tpo" -c -o libiksemel_la-ikstack.lo `test -f 'ikstack.c' || echo '$(srcdir)/'`ikstack.c; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libiksemel_la-ikstack.Tpo" "$(DEPDIR)/libiksemel_la-ikstack.Plo"; else rm -f "$(DEPDIR)/libiksemel_la-ikstack.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='ikstack.c' object='libiksemel_la-ikstack.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libiksemel_la_CFLAGS) $(CFLAGS) -c -o libiksemel_la-ikstack.lo `test -f 'ikstack.c' || echo '$(srcdir)/'`ikstack.c
+
+libiksemel_la-utility.lo: utility.c
+@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libiksemel_la_CFLAGS) $(CFLAGS) -MT libiksemel_la-utility.lo -MD -MP -MF "$(DEPDIR)/libiksemel_la-utility.Tpo" -c -o libiksemel_la-utility.lo `test -f 'utility.c' || echo '$(srcdir)/'`utility.c; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libiksemel_la-utility.Tpo" "$(DEPDIR)/libiksemel_la-utility.Plo"; else rm -f "$(DEPDIR)/libiksemel_la-utility.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='utility.c' object='libiksemel_la-utility.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libiksemel_la_CFLAGS) $(CFLAGS) -c -o libiksemel_la-utility.lo `test -f 'utility.c' || echo '$(srcdir)/'`utility.c
+
+libiksemel_la-iks.lo: iks.c
+@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libiksemel_la_CFLAGS) $(CFLAGS) -MT libiksemel_la-iks.lo -MD -MP -MF "$(DEPDIR)/libiksemel_la-iks.Tpo" -c -o libiksemel_la-iks.lo `test -f 'iks.c' || echo '$(srcdir)/'`iks.c; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libiksemel_la-iks.Tpo" "$(DEPDIR)/libiksemel_la-iks.Plo"; else rm -f "$(DEPDIR)/libiksemel_la-iks.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='iks.c' object='libiksemel_la-iks.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libiksemel_la_CFLAGS) $(CFLAGS) -c -o libiksemel_la-iks.lo `test -f 'iks.c' || echo '$(srcdir)/'`iks.c
+
+libiksemel_la-sax.lo: sax.c
+@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libiksemel_la_CFLAGS) $(CFLAGS) -MT libiksemel_la-sax.lo -MD -MP -MF "$(DEPDIR)/libiksemel_la-sax.Tpo" -c -o libiksemel_la-sax.lo `test -f 'sax.c' || echo '$(srcdir)/'`sax.c; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libiksemel_la-sax.Tpo" "$(DEPDIR)/libiksemel_la-sax.Plo"; else rm -f "$(DEPDIR)/libiksemel_la-sax.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sax.c' object='libiksemel_la-sax.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libiksemel_la_CFLAGS) $(CFLAGS) -c -o libiksemel_la-sax.lo `test -f 'sax.c' || echo '$(srcdir)/'`sax.c
+
+libiksemel_la-dom.lo: dom.c
+@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libiksemel_la_CFLAGS) $(CFLAGS) -MT libiksemel_la-dom.lo -MD -MP -MF "$(DEPDIR)/libiksemel_la-dom.Tpo" -c -o libiksemel_la-dom.lo `test -f 'dom.c' || echo '$(srcdir)/'`dom.c; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libiksemel_la-dom.Tpo" "$(DEPDIR)/libiksemel_la-dom.Plo"; else rm -f "$(DEPDIR)/libiksemel_la-dom.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='dom.c' object='libiksemel_la-dom.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libiksemel_la_CFLAGS) $(CFLAGS) -c -o libiksemel_la-dom.lo `test -f 'dom.c' || echo '$(srcdir)/'`dom.c
+
+libiksemel_la-io-posix.lo: io-posix.c
+@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libiksemel_la_CFLAGS) $(CFLAGS) -MT libiksemel_la-io-posix.lo -MD -MP -MF "$(DEPDIR)/libiksemel_la-io-posix.Tpo" -c -o libiksemel_la-io-posix.lo `test -f 'io-posix.c' || echo '$(srcdir)/'`io-posix.c; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libiksemel_la-io-posix.Tpo" "$(DEPDIR)/libiksemel_la-io-posix.Plo"; else rm -f "$(DEPDIR)/libiksemel_la-io-posix.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='io-posix.c' object='libiksemel_la-io-posix.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libiksemel_la_CFLAGS) $(CFLAGS) -c -o libiksemel_la-io-posix.lo `test -f 'io-posix.c' || echo '$(srcdir)/'`io-posix.c
+
+libiksemel_la-stream.lo: stream.c
+@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libiksemel_la_CFLAGS) $(CFLAGS) -MT libiksemel_la-stream.lo -MD -MP -MF "$(DEPDIR)/libiksemel_la-stream.Tpo" -c -o libiksemel_la-stream.lo `test -f 'stream.c' || echo '$(srcdir)/'`stream.c; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libiksemel_la-stream.Tpo" "$(DEPDIR)/libiksemel_la-stream.Plo"; else rm -f "$(DEPDIR)/libiksemel_la-stream.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='stream.c' object='libiksemel_la-stream.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libiksemel_la_CFLAGS) $(CFLAGS) -c -o libiksemel_la-stream.lo `test -f 'stream.c' || echo '$(srcdir)/'`stream.c
+
+libiksemel_la-sha.lo: sha.c
+@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libiksemel_la_CFLAGS) $(CFLAGS) -MT libiksemel_la-sha.lo -MD -MP -MF "$(DEPDIR)/libiksemel_la-sha.Tpo" -c -o libiksemel_la-sha.lo `test -f 'sha.c' || echo '$(srcdir)/'`sha.c; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libiksemel_la-sha.Tpo" "$(DEPDIR)/libiksemel_la-sha.Plo"; else rm -f "$(DEPDIR)/libiksemel_la-sha.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='sha.c' object='libiksemel_la-sha.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libiksemel_la_CFLAGS) $(CFLAGS) -c -o libiksemel_la-sha.lo `test -f 'sha.c' || echo '$(srcdir)/'`sha.c
+
+libiksemel_la-jabber.lo: jabber.c
+@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libiksemel_la_CFLAGS) $(CFLAGS) -MT libiksemel_la-jabber.lo -MD -MP -MF "$(DEPDIR)/libiksemel_la-jabber.Tpo" -c -o libiksemel_la-jabber.lo `test -f 'jabber.c' || echo '$(srcdir)/'`jabber.c; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libiksemel_la-jabber.Tpo" "$(DEPDIR)/libiksemel_la-jabber.Plo"; else rm -f "$(DEPDIR)/libiksemel_la-jabber.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='jabber.c' object='libiksemel_la-jabber.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libiksemel_la_CFLAGS) $(CFLAGS) -c -o libiksemel_la-jabber.lo `test -f 'jabber.c' || echo '$(srcdir)/'`jabber.c
+
+libiksemel_la-filter.lo: filter.c
+@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libiksemel_la_CFLAGS) $(CFLAGS) -MT libiksemel_la-filter.lo -MD -MP -MF "$(DEPDIR)/libiksemel_la-filter.Tpo" -c -o libiksemel_la-filter.lo `test -f 'filter.c' || echo '$(srcdir)/'`filter.c; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libiksemel_la-filter.Tpo" "$(DEPDIR)/libiksemel_la-filter.Plo"; else rm -f "$(DEPDIR)/libiksemel_la-filter.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='filter.c' object='libiksemel_la-filter.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libiksemel_la_CFLAGS) $(CFLAGS) -c -o libiksemel_la-filter.lo `test -f 'filter.c' || echo '$(srcdir)/'`filter.c
+
+libiksemel_la-md5.lo: md5.c
+@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libiksemel_la_CFLAGS) $(CFLAGS) -MT libiksemel_la-md5.lo -MD -MP -MF "$(DEPDIR)/libiksemel_la-md5.Tpo" -c -o libiksemel_la-md5.lo `test -f 'md5.c' || echo '$(srcdir)/'`md5.c; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libiksemel_la-md5.Tpo" "$(DEPDIR)/libiksemel_la-md5.Plo"; else rm -f "$(DEPDIR)/libiksemel_la-md5.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='md5.c' object='libiksemel_la-md5.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libiksemel_la_CFLAGS) $(CFLAGS) -c -o libiksemel_la-md5.lo `test -f 'md5.c' || echo '$(srcdir)/'`md5.c
+
+libiksemel_la-base64.lo: base64.c
+@am__fastdepCC_TRUE@ if $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libiksemel_la_CFLAGS) $(CFLAGS) -MT libiksemel_la-base64.lo -MD -MP -MF "$(DEPDIR)/libiksemel_la-base64.Tpo" -c -o libiksemel_la-base64.lo `test -f 'base64.c' || echo '$(srcdir)/'`base64.c; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/libiksemel_la-base64.Tpo" "$(DEPDIR)/libiksemel_la-base64.Plo"; else rm -f "$(DEPDIR)/libiksemel_la-base64.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='base64.c' object='libiksemel_la-base64.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libiksemel_la_CFLAGS) $(CFLAGS) -c -o libiksemel_la-base64.lo `test -f 'base64.c' || echo '$(srcdir)/'`base64.c
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool
+uninstall-info-am:
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+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)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkdir_p) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$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)
+installdirs:
+ for dir in "$(DESTDIR)$(libdir)"; 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:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_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-libLTLIBRARIES clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-libtool distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-exec-am: install-libLTLIBRARIES
+
+install-info: install-info-am
+
+install-man:
+
+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-info-am uninstall-libLTLIBRARIES
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libLTLIBRARIES clean-libtool ctags 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-exec \
+ install-exec-am install-info install-info-am \
+ install-libLTLIBRARIES install-man 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 uninstall uninstall-am uninstall-info-am \
+ uninstall-libLTLIBRARIES
+
+# 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:
diff --git a/src/base64.c b/src/base64.c
new file mode 100644
index 0000000..bb89ce8
--- /dev/null
+++ b/src/base64.c
@@ -0,0 +1,103 @@
+/* iksemel (XML parser for Jabber)
+** Copyright (C) 2000-2003 Gurer Ozen <madcat@e-kolay.net>
+** This code is free software; you can redistribute it and/or
+** modify it under the terms of GNU Lesser General Public License.
+*/
+
+#include "common.h"
+#include "iksemel.h"
+
+static const char base64_charset[] =
+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+
+char *iks_base64_decode(const char *buf)
+{
+ char *res, *save;
+ char val;
+ const char *foo;
+ const char *end;
+ int index;
+ size_t len;
+
+ if (!buf)
+ return NULL;
+
+ len = iks_strlen(buf) * 6 / 8 + 1;
+
+ save = res = iks_malloc(len);
+ if (!save)
+ return NULL;
+ memset(res, 0, len);
+
+ index = 0;
+ end = buf + iks_strlen(buf);
+
+ while (*buf && buf < end) {
+ if (!(foo = strchr(base64_charset, *buf)))
+ foo = base64_charset;
+ val = (int)(foo - base64_charset);
+ buf++;
+ switch (index) {
+ case 0:
+ *res |= val << 2;
+ break;
+ case 1:
+ *res++ |= val >> 4;
+ *res |= val << 4;
+ break;
+ case 2:
+ *res++ |= val >> 2;
+ *res |= val << 6;
+ break;
+ case 3:
+ *res++ |= val;
+ break;
+ }
+ index++;
+ index %= 4;
+ }
+ *res = 0;
+
+ return save;
+}
+
+char *iks_base64_encode(const char *buf, int len)
+{
+ char *res, *save;
+ int k, t;
+
+ len = (len > 0) ? (len) : (iks_strlen(buf));
+ save = res = iks_malloc((len*8) / 6 + 4);
+ if (!save) return NULL;
+
+ for (k = 0; k < len/3; ++k) {
+ *res++ = base64_charset[*buf >> 2];
+ t = ((*buf & 0x03) << 4);
+ buf++;
+ *res++ = base64_charset[t | (*buf >> 4)];
+ t = ((*buf & 0x0F) << 2);
+ buf++;
+ *res++ = base64_charset[t | (*buf >> 6)];
+ *res++ = base64_charset[*buf++ & 0x3F];
+ }
+
+ switch (len % 3) {
+ case 2:
+ *res++ = base64_charset[*buf >> 2];
+ t = ((*buf & 0x03) << 4);
+ buf++;
+ *res++ = base64_charset[t | (*buf >> 4)];
+ *res++ = base64_charset[((*buf++ & 0x0F) << 2)];
+ *res++ = '=';
+ break;
+ case 1:
+ *res++ = base64_charset[*buf >> 2];
+ *res++ = base64_charset[(*buf++ & 0x03) << 4];
+ *res++ = '=';
+ *res++ = '=';
+ break;
+ }
+ *res = 0;
+ return save;
+}
diff --git a/src/dom.c b/src/dom.c
new file mode 100644
index 0000000..849bf20
--- /dev/null
+++ b/src/dom.c
@@ -0,0 +1,181 @@
+/* iksemel (XML parser for Jabber)
+** Copyright (C) 2000-2003 Gurer Ozen <madcat@e-kolay.net>
+** This code is free software; you can redistribute it and/or
+** modify it under the terms of GNU Lesser General Public License.
+*/
+
+#include "common.h"
+#include "iksemel.h"
+
+struct dom_data {
+ iks **iksptr;
+ iks *current;
+ size_t chunk_size;
+};
+
+static int
+tagHook (struct dom_data *data, char *name, char **atts, int type)
+{
+ iks *x;
+
+ if (IKS_OPEN == type || IKS_SINGLE == type) {
+ if (data->current) {
+ x = iks_insert (data->current, name);
+ } else {
+ ikstack *s;
+ s = iks_stack_new (data->chunk_size, data->chunk_size);
+ x = iks_new_within (name, s);
+ }
+ if (atts) {
+ int i=0;
+ while (atts[i]) {
+ iks_insert_attrib (x, atts[i], atts[i+1]);
+ i += 2;
+ }
+ }
+ data->current = x;
+ }
+ if (IKS_CLOSE == type || IKS_SINGLE == type) {
+ x = iks_parent (data->current);
+ if (iks_strcmp(iks_name(data->current), name) != 0)
+ return IKS_BADXML;
+ if (x)
+ data->current = x;
+ else {
+ *(data->iksptr) = data->current;
+ data->current = NULL;
+ }
+ }
+ return IKS_OK;
+}
+
+static int
+cdataHook (struct dom_data *data, char *cdata, size_t len)
+{
+ if (data->current) iks_insert_cdata (data->current, cdata, len);
+ return IKS_OK;
+}
+
+static void
+deleteHook (struct dom_data *data)
+{
+ if (data->current) iks_delete (data->current);
+ data->current = NULL;
+}
+
+iksparser *
+iks_dom_new (iks **iksptr)
+{
+ ikstack *s;
+ struct dom_data *data;
+
+ *iksptr = NULL;
+ s = iks_stack_new (DEFAULT_DOM_CHUNK_SIZE, 0);
+ if (!s) return NULL;
+ data = iks_stack_alloc (s, sizeof (struct dom_data));
+ data->iksptr = iksptr;
+ data->current = NULL;
+ data->chunk_size = DEFAULT_DOM_IKS_CHUNK_SIZE;
+ return iks_sax_extend (s, data, (iksTagHook *) tagHook, (iksCDataHook *) cdataHook, (iksDeleteHook *) deleteHook);
+}
+
+void
+iks_set_size_hint (iksparser *prs, size_t approx_size)
+{
+ size_t cs;
+ struct dom_data *data = iks_user_data (prs);
+
+ cs = approx_size / 10;
+ if (cs < DEFAULT_DOM_IKS_CHUNK_SIZE) cs = DEFAULT_DOM_IKS_CHUNK_SIZE;
+ data->chunk_size = cs;
+}
+
+iks *
+iks_tree (const char *xml_str, size_t len, int *err)
+{
+ iksparser *prs;
+ iks *x;
+ int e;
+
+ if (0 == len) len = strlen (xml_str);
+ prs = iks_dom_new (&x);
+ if (!prs) {
+ if (err) *err = IKS_NOMEM;
+ return NULL;
+ }
+ e = iks_parse (prs, xml_str, len, 1);
+ if (err) *err = e;
+ iks_parser_delete (prs);
+ return x;
+}
+
+int
+iks_load (const char *fname, iks **xptr)
+{
+ iksparser *prs;
+ char *buf;
+ FILE *f;
+ int len, done = 0;
+ int ret;
+
+ *xptr = NULL;
+
+ buf = iks_malloc (FILE_IO_BUF_SIZE);
+ if (!buf) return IKS_NOMEM;
+ ret = IKS_NOMEM;
+ prs = iks_dom_new (xptr);
+ if (prs) {
+ f = fopen (fname, "r");
+ if (f) {
+ while (0 == done) {
+ len = fread (buf, 1, FILE_IO_BUF_SIZE, f);
+ if (len < FILE_IO_BUF_SIZE) {
+ if (0 == feof (f)) {
+ ret = IKS_FILE_RWERR;
+ break;
+ }
+ if (0 == len) ret = IKS_OK;
+ done = 1;
+ }
+ if (len > 0) {
+ int e;
+ e = iks_parse (prs, buf, len, done);
+ if (IKS_OK != e) {
+ ret = e;
+ break;
+ }
+ if (done) ret = IKS_OK;
+ }
+ }
+ fclose (f);
+ } else {
+ if (ENOENT == errno) ret = IKS_FILE_NOFILE;
+ else ret = IKS_FILE_NOACCESS;
+ }
+ iks_parser_delete (prs);
+ }
+ iks_free (buf);
+ return ret;
+}
+
+int
+iks_save (const char *fname, iks *x)
+{
+ FILE *f;
+ char *data;
+ int ret;
+
+ ret = IKS_NOMEM;
+ data = iks_string (NULL, x);
+ if (data) {
+ ret = IKS_FILE_NOACCESS;
+ f = fopen (fname, "w");
+ if (f) {
+ ret = IKS_FILE_RWERR;
+ if (fputs (data, f) >= 0) ret = IKS_OK;
+ fclose (f);
+ }
+ iks_free (data);
+ }
+ return ret;
+}
diff --git a/src/filter.c b/src/filter.c
new file mode 100644
index 0000000..9af451f
--- /dev/null
+++ b/src/filter.c
@@ -0,0 +1,181 @@
+/* iksemel (XML parser for Jabber)
+** Copyright (C) 2000-2003 Gurer Ozen <madcat@e-kolay.net>
+** This code is free software; you can redistribute it and/or
+** modify it under the terms of GNU Lesser General Public License.
+*/
+
+#include "common.h"
+#include "iksemel.h"
+
+struct iksrule_struct {
+ struct iksrule_struct *next, *prev;
+ ikstack *s;
+ void *user_data;
+ iksFilterHook *filterHook;
+ char *id;
+ char *from;
+ char *ns;
+ int score;
+ int rules;
+ enum ikstype type;
+ enum iksubtype subtype;
+};
+
+struct iksfilter_struct {
+ iksrule *rules;
+ iksrule *last_rule;
+};
+
+iksfilter *
+iks_filter_new (void)
+{
+ iksfilter *f;
+
+ f = iks_malloc (sizeof (iksfilter));
+ if (!f) return NULL;
+ memset (f, 0, sizeof (iksfilter));
+
+ return f;
+}
+
+iksrule *
+iks_filter_add_rule (iksfilter *f, iksFilterHook *filterHook, void *user_data, ...)
+{
+ ikstack *s;
+ iksrule *rule;
+ va_list ap;
+ int type;
+
+ s = iks_stack_new (sizeof (iksrule), DEFAULT_RULE_CHUNK_SIZE);
+ if (!s) return NULL;
+ rule = iks_stack_alloc (s, sizeof (iksrule));
+ memset (rule, 0, sizeof (iksrule));
+ rule->s = s;
+ rule->user_data = user_data;
+ rule->filterHook = filterHook;
+
+ va_start (ap, user_data);
+ while (1) {
+ type = va_arg (ap, int);
+ if (IKS_RULE_DONE == type) break;
+ rule->rules += type;
+ switch (type) {
+ case IKS_RULE_TYPE:
+ rule->type = va_arg (ap, int);
+ break;
+ case IKS_RULE_SUBTYPE:
+ rule->subtype = va_arg (ap, int);
+ break;
+ case IKS_RULE_ID:
+ rule->id = iks_stack_strdup (s, va_arg (ap, char *), 0);
+ break;
+ case IKS_RULE_NS:
+ rule->ns = iks_stack_strdup (s, va_arg (ap, char *), 0);
+ break;
+ case IKS_RULE_FROM:
+ rule->from = iks_stack_strdup (s, va_arg (ap, char *), 0);
+ break;
+ case IKS_RULE_FROM_PARTIAL:
+ rule->from = iks_stack_strdup (s, va_arg (ap, char *), 0);
+ break;
+ }
+ }
+ va_end (ap);
+
+ if (!f->rules) f->rules = rule;
+ if (f->last_rule) f->last_rule->next = rule;
+ rule->prev = f->last_rule;
+ f->last_rule = rule;
+ return rule;
+}
+
+void
+iks_filter_remove_rule (iksfilter *f, iksrule *rule)
+{
+ if (rule->prev) rule->prev->next = rule->next;
+ if (rule->next) rule->next->prev = rule->prev;
+ if (f->rules == rule) f->rules = rule->next;
+ if (f->last_rule == rule) f->last_rule = rule->prev;
+ iks_stack_delete (rule->s);
+}
+
+void
+iks_filter_remove_hook (iksfilter *f, iksFilterHook *filterHook)
+{
+ iksrule *rule, *tmp;
+
+ rule = f->rules;
+ while (rule) {
+ tmp = rule->next;
+ if (rule->filterHook == filterHook) iks_filter_remove_rule (f, rule);
+ rule = tmp;
+ }
+}
+
+void
+iks_filter_packet (iksfilter *f, ikspak *pak)
+{
+ iksrule *rule, *max_rule;
+ int fail, score, max_score;
+
+ rule = f->rules;
+ max_rule = NULL;
+ max_score = 0;
+ while (rule) {
+ score = 0;
+ fail = 0;
+ if (rule->rules & IKS_RULE_TYPE) {
+ if (rule->type == pak->type) score += 1; else fail = 1;
+ }
+ if (rule->rules & IKS_RULE_SUBTYPE) {
+ if (rule->subtype == pak->subtype) score += 2; else fail = 1;
+ }
+ if (rule->rules & IKS_RULE_ID) {
+ if (iks_strcmp (rule->id, pak->id) == 0) score += 16; else fail = 1;
+ }
+ if (rule->rules & IKS_RULE_NS) {
+ if (iks_strcmp (rule->ns, pak->ns) == 0) score += 4; else fail = 1;
+ }
+ if (rule->rules & IKS_RULE_FROM) {
+ if (pak->from && iks_strcmp (rule->from, pak->from->full) == 0) score += 8; else fail = 1;
+ }
+ if (rule->rules & IKS_RULE_FROM_PARTIAL) {
+ if (pak->from && iks_strcmp (rule->from, pak->from->partial) == 0) score += 8; else fail = 1;
+ }
+ if (fail != 0) score = 0;
+ rule->score = score;
+ if (score > max_score) {
+ max_rule = rule;
+ max_score = score;
+ }
+ rule = rule->next;
+ }
+ while (max_rule) {
+ if (IKS_FILTER_EAT == max_rule->filterHook (max_rule->user_data, pak)) return;
+ max_rule->score = 0;
+ max_rule = NULL;
+ max_score = 0;
+ rule = f->rules;
+ while (rule) {
+ if (rule->score > max_score) {
+ max_rule = rule;
+ max_score = rule->score;
+ }
+ rule = rule->next;
+ }
+ }
+}
+
+void
+iks_filter_delete (iksfilter *f)
+{
+ iksrule *rule, *tmp;
+
+ rule = f->rules;
+ while (rule) {
+ tmp = rule->next;
+ iks_stack_delete (rule->s);
+ rule = tmp;
+ }
+ iks_free (f);
+}
diff --git a/src/iks.c b/src/iks.c
new file mode 100644
index 0000000..fe61f79
--- /dev/null
+++ b/src/iks.c
@@ -0,0 +1,762 @@
+/* iksemel (XML parser for Jabber)
+** Copyright (C) 2000-2007 Gurer Ozen <madcat@e-kolay.net>
+** This code is free software; you can redistribute it and/or
+** modify it under the terms of GNU Lesser General Public License.
+*/
+
+#include "common.h"
+#include "iksemel.h"
+
+#define IKS_COMMON \
+ struct iks_struct *next, *prev; \
+ struct iks_struct *parent; \
+ enum ikstype type; \
+ ikstack *s
+
+struct iks_struct {
+ IKS_COMMON;
+};
+
+struct iks_tag {
+ IKS_COMMON;
+ struct iks_struct *children, *last_child;
+ struct iks_struct *attribs, *last_attrib;
+ char *name;
+};
+
+#define IKS_TAG_NAME(x) ((struct iks_tag *) (x) )->name
+#define IKS_TAG_CHILDREN(x) ((struct iks_tag *) (x) )->children
+#define IKS_TAG_LAST_CHILD(x) ((struct iks_tag *) (x) )->last_child
+#define IKS_TAG_ATTRIBS(x) ((struct iks_tag *) (x) )->attribs
+#define IKS_TAG_LAST_ATTRIB(x) ((struct iks_tag *) (x) )->last_attrib
+
+struct iks_cdata {
+ IKS_COMMON;
+ char *cdata;
+ size_t len;
+};
+
+#define IKS_CDATA_CDATA(x) ((struct iks_cdata *) (x) )->cdata
+#define IKS_CDATA_LEN(x) ((struct iks_cdata *) (x) )->len
+
+struct iks_attrib {
+ IKS_COMMON;
+ char *name;
+ char *value;
+};
+
+#define IKS_ATTRIB_NAME(x) ((struct iks_attrib *) (x) )->name
+#define IKS_ATTRIB_VALUE(x) ((struct iks_attrib *) (x) )->value
+
+/***** Node Creating & Deleting *****/
+
+iks *
+iks_new (const char *name)
+{
+ ikstack *s;
+ iks *x;
+
+ s = iks_stack_new (sizeof (struct iks_tag) * 6, 256);
+ if (!s) return NULL;
+ x = iks_new_within (name, s);
+ if (!x) {
+ iks_stack_delete (s);
+ return NULL;
+ }
+ return x;
+}
+
+iks *
+iks_new_within (const char *name, ikstack *s)
+{
+ iks *x;
+ size_t len;
+
+ if (name) len = sizeof (struct iks_tag); else len = sizeof (struct iks_cdata);
+ x = iks_stack_alloc (s, len);
+ if (!x) return NULL;
+ memset (x, 0, len);
+ x->s = s;
+ x->type = IKS_TAG;
+ if (name) {
+ IKS_TAG_NAME (x) = iks_stack_strdup (s, name, 0);
+ if (!IKS_TAG_NAME (x)) return NULL;
+ }
+ return x;
+}
+
+iks *
+iks_insert (iks *x, const char *name)
+{
+ iks *y;
+
+ if (!x) return NULL;
+
+ y = iks_new_within (name, x->s);
+ if (!y) return NULL;
+ y->parent = x;
+ if (!IKS_TAG_CHILDREN (x)) IKS_TAG_CHILDREN (x) = y;
+ if (IKS_TAG_LAST_CHILD (x)) {
+ IKS_TAG_LAST_CHILD (x)->next = y;
+ y->prev = IKS_TAG_LAST_CHILD (x);
+ }
+ IKS_TAG_LAST_CHILD (x) = y;
+ return y;
+}
+
+iks *
+iks_insert_cdata (iks *x, const char *data, size_t len)
+{
+ iks *y;
+
+ if(!x || !data) return NULL;
+ if(len == 0) len = strlen (data);
+
+ y = IKS_TAG_LAST_CHILD (x);
+ if (y && y->type == IKS_CDATA) {
+ IKS_CDATA_CDATA (y) = iks_stack_strcat (x->s, IKS_CDATA_CDATA (y), IKS_CDATA_LEN (y), data, len);
+ IKS_CDATA_LEN (y) += len;
+ } else {
+ y = iks_insert (x, NULL);
+ if (!y) return NULL;
+ y->type = IKS_CDATA;
+ IKS_CDATA_CDATA (y) = iks_stack_strdup (x->s, data, len);
+ if (!IKS_CDATA_CDATA (y)) return NULL;
+ IKS_CDATA_LEN (y) = len;
+ }
+ return y;
+}
+
+iks *
+iks_insert_attrib (iks *x, const char *name, const char *value)
+{
+ iks *y;
+
+ if (!x) return NULL;
+
+ y = IKS_TAG_ATTRIBS (x);
+ while (y) {
+ if (strcmp (name, IKS_ATTRIB_NAME (y)) == 0) break;
+ y = y->next;
+ }
+ if (NULL == y) {
+ if (!value) return NULL;
+ y = iks_stack_alloc (x->s, sizeof (struct iks_attrib));
+ if (!y) return NULL;
+ memset (y, 0, sizeof (struct iks_attrib));
+ y->type = IKS_ATTRIBUTE;
+ y->s = x->s;
+ IKS_ATTRIB_NAME (y) = iks_stack_strdup (x->s, name, 0);
+ if (!IKS_ATTRIB_NAME (y)) return NULL;
+ y->parent = x;
+ if (!IKS_TAG_ATTRIBS (x)) IKS_TAG_ATTRIBS (x) = y;
+ if (IKS_TAG_LAST_ATTRIB (x)) {
+ IKS_TAG_LAST_ATTRIB (x)->next = y;
+ y->prev = IKS_TAG_LAST_ATTRIB (x);
+ }
+ IKS_TAG_LAST_ATTRIB (x) = y;
+ }
+
+ if (value) {
+ IKS_ATTRIB_VALUE (y) = iks_stack_strdup (x->s, value, 0);
+ if (!IKS_ATTRIB_VALUE (y)) return NULL;
+ } else {
+ if (y->next) y->next->prev = y->prev;
+ if (y->prev) y->prev->next = y->next;
+ if (IKS_TAG_ATTRIBS (x) == y) IKS_TAG_ATTRIBS (x) = y->next;
+ if (IKS_TAG_LAST_ATTRIB (x) == y) IKS_TAG_LAST_ATTRIB (x) = y->prev;
+ }
+
+ return y;
+}
+
+iks *
+iks_insert_node (iks *x, iks *y)
+{
+ y->parent = x;
+ if (!IKS_TAG_CHILDREN (x)) IKS_TAG_CHILDREN (x) = y;
+ if (IKS_TAG_LAST_CHILD (x)) {
+ IKS_TAG_LAST_CHILD (x)->next = y;
+ y->prev = IKS_TAG_LAST_CHILD (x);
+ }
+ IKS_TAG_LAST_CHILD (x) = y;
+ return y;
+}
+
+iks *
+iks_append (iks *x, const char *name)
+{
+ iks *y;
+
+ if (!x) return NULL;
+ y = iks_new_within (name, x->s);
+ if (!y) return NULL;
+
+ if (x->next) {
+ x->next->prev = y;
+ } else {
+ IKS_TAG_LAST_CHILD (x->parent) = y;
+ }
+ y->next = x->next;
+ x->next = y;
+ y->parent = x->parent;
+ y->prev = x;
+
+ return y;
+}
+
+iks *
+iks_prepend (iks *x, const char *name)
+{
+ iks *y;
+
+ if (!x) return NULL;
+ y = iks_new_within (name, x->s);
+ if (!y) return NULL;
+
+ if (x->prev) {
+ x->prev->next = y;
+ } else {
+ IKS_TAG_CHILDREN (x->parent) = y;
+ }
+ y->prev = x->prev;
+ x->prev = y;
+ y->parent = x->parent;
+ y->next = x;
+
+ return y;
+}
+
+iks *
+iks_append_cdata (iks *x, const char *data, size_t len)
+{
+ iks *y;
+
+ if (!x || !data) return NULL;
+ if (len == 0) len = strlen (data);
+
+ y = iks_new_within (NULL, x->s);
+ if (!y) return NULL;
+ y->type = IKS_CDATA;
+ IKS_CDATA_CDATA (y) = iks_stack_strdup (x->s, data, len);
+ if (!IKS_CDATA_CDATA (y)) return NULL;
+ IKS_CDATA_LEN (y) = len;
+
+ if (x->next) {
+ x->next->prev = y;
+ } else {
+ IKS_TAG_LAST_CHILD (x->parent) = y;
+ }
+ y->next = x->next;
+ x->next = y;
+ y->parent = x->parent;
+ y->prev = x;
+
+ return y;
+}
+
+iks *
+iks_prepend_cdata (iks *x, const char *data, size_t len)
+{
+ iks *y;
+
+ if (!x || !data) return NULL;
+ if (len == 0) len = strlen (data);
+
+ y = iks_new_within (NULL, x->s);
+ if (!y) return NULL;
+ y->type = IKS_CDATA;
+ IKS_CDATA_CDATA(y) = iks_stack_strdup (x->s, data, len);
+ if (!IKS_CDATA_CDATA (y)) return NULL;
+ IKS_CDATA_LEN (y) = len;
+
+ if (x->prev) {
+ x->prev->next = y;
+ } else {
+ IKS_TAG_CHILDREN (x->parent) = y;
+ }
+ y->prev = x->prev;
+ x->prev = y;
+ y->parent = x->parent;
+ y->next = x;
+
+ return y;
+}
+
+void
+iks_hide (iks *x)
+{
+ iks *y;
+
+ if (!x) return;
+
+ if (x->prev) x->prev->next = x->next;
+ if (x->next) x->next->prev = x->prev;
+ y = x->parent;
+ if (y) {
+ if (IKS_TAG_CHILDREN (y) == x) IKS_TAG_CHILDREN (y) = x->next;
+ if (IKS_TAG_LAST_CHILD (y) == x) IKS_TAG_LAST_CHILD (y) = x->prev;
+ }
+}
+
+void
+iks_delete (iks *x)
+{
+ if (x) iks_stack_delete (x->s);
+}
+
+/***** Node Traversing *****/
+
+iks *
+iks_next (iks *x)
+{
+ if (x) return x->next;
+ return NULL;
+}
+
+iks *
+iks_next_tag (iks *x)
+{
+ if (x) {
+ while (1) {
+ x = x->next;
+ if (NULL == x) break;
+ if (IKS_TAG == x->type) return x;
+ }
+ }
+ return NULL;
+}
+
+iks *
+iks_prev (iks *x)
+{
+ if (x) return x->prev;
+ return NULL;
+}
+
+iks *
+iks_prev_tag (iks *x)
+{
+ if (x) {
+ while (1) {
+ x = x->prev;
+ if (NULL == x) break;
+ if (IKS_TAG == x->type) return x;
+ }
+ }
+ return NULL;
+}
+
+iks *
+iks_parent (iks *x)
+{
+ if (x) return x->parent;
+ return NULL;
+}
+
+iks *
+iks_root (iks *x)
+{
+ if (x) {
+ while (x->parent)
+ x = x->parent;
+ }
+ return x;
+}
+
+iks *
+iks_child (iks *x)
+{
+ if (x && IKS_TAG == x->type) return IKS_TAG_CHILDREN (x);
+ return NULL;
+}
+
+iks *
+iks_first_tag (iks *x)
+{
+ if (x) {
+ x = IKS_TAG_CHILDREN (x);
+ while (x) {
+ if (IKS_TAG == x->type) return x;
+ x = x->next;
+ }
+ }
+ return NULL;
+}
+
+iks *
+iks_attrib (iks *x)
+{
+ if (x) return IKS_TAG_ATTRIBS (x);
+ return NULL;
+}
+
+iks *
+iks_find (iks *x, const char *name)
+{
+ iks *y;
+
+ if (!x) return NULL;
+ y = IKS_TAG_CHILDREN (x);
+ while (y) {
+ if (IKS_TAG == y->type && IKS_TAG_NAME (y) && strcmp (IKS_TAG_NAME (y), name) == 0) return y;
+ y = y->next;
+ }
+ return NULL;
+}
+
+char *
+iks_find_cdata (iks *x, const char *name)
+{
+ iks *y;
+
+ y = iks_find (x, name);
+ if (!y) return NULL;
+ y = IKS_TAG_CHILDREN (y);
+ if (!y || IKS_CDATA != y->type) return NULL;
+ return IKS_CDATA_CDATA (y);
+}
+
+char *
+iks_find_attrib (iks *x, const char *name)
+{
+ iks *y;
+
+ if (!x) return NULL;
+
+ y = IKS_TAG_ATTRIBS (x);
+ while (y) {
+ if (IKS_ATTRIB_NAME (y) && strcmp (IKS_ATTRIB_NAME (y), name) == 0)
+ return IKS_ATTRIB_VALUE (y);
+ y = y->next;
+ }
+ return NULL;
+}
+
+iks *
+iks_find_with_attrib (iks *x, const char *tagname, const char *attrname, const char *value)
+{
+ iks *y;
+
+ if (NULL == x) return NULL;
+
+ if (tagname) {
+ for (y = IKS_TAG_CHILDREN (x); y; y = y->next) {
+ if (IKS_TAG == y->type
+ && strcmp (IKS_TAG_NAME (y), tagname) == 0
+ && iks_strcmp (iks_find_attrib (y, attrname), value) == 0) {
+ return y;
+ }
+ }
+ } else {
+ for (y = IKS_TAG_CHILDREN (x); y; y = y->next) {
+ if (IKS_TAG == y->type
+ && iks_strcmp (iks_find_attrib (y, attrname), value) == 0) {
+ return y;
+ }
+ }
+ }
+ return NULL;
+}
+
+/***** Node Information *****/
+
+ikstack *
+iks_stack (iks *x)
+{
+ if (x) return x->s;
+ return NULL;
+}
+
+enum ikstype
+iks_type (iks *x)
+{
+ if (x) return x->type;
+ return IKS_NONE;
+}
+
+char *
+iks_name (iks *x)
+{
+ if (x) {
+ if (IKS_TAG == x->type)
+ return IKS_TAG_NAME (x);
+ else
+ return IKS_ATTRIB_NAME (x);
+ }
+ return NULL;
+}
+
+char *
+iks_cdata (iks *x)
+{
+ if (x) {
+ if (IKS_CDATA == x->type)
+ return IKS_CDATA_CDATA (x);
+ else
+ return IKS_ATTRIB_VALUE (x);
+ }
+ return NULL;
+}
+
+size_t
+iks_cdata_size (iks *x)
+{
+ if (x) return IKS_CDATA_LEN (x);
+ return 0;
+}
+
+int
+iks_has_children (iks *x)
+{
+ if (x && IKS_TAG == x->type && IKS_TAG_CHILDREN (x)) return 1;
+ return 0;
+}
+
+int
+iks_has_attribs (iks *x)
+{
+ if (x && IKS_TAG == x->type && IKS_TAG_ATTRIBS (x)) return 1;
+ return 0;
+}
+
+/***** Serializing *****/
+
+static size_t
+escape_size (char *src, size_t len)
+{
+ size_t sz;
+ char c;
+ int i;
+
+ sz = 0;
+ for (i = 0; i < len; i++) {
+ c = src[i];
+ switch (c) {
+ case '&': sz += 5; break;
+ case '\'': sz += 6; break;
+ case '"': sz += 6; break;
+ case '<': sz += 4; break;
+ case '>': sz += 4; break;
+ default: sz++; break;
+ }
+ }
+ return sz;
+}
+
+static char *
+my_strcat (char *dest, char *src, size_t len)
+{
+ if (0 == len) len = strlen (src);
+ memcpy (dest, src, len);
+ return dest + len;
+}
+
+static char *
+escape (char *dest, char *src, size_t len)
+{
+ char c;
+ int i;
+ int j = 0;
+
+ for (i = 0; i < len; i++) {
+ c = src[i];
+ if ('&' == c || '<' == c || '>' == c || '\'' == c || '"' == c) {
+ if (i - j > 0) dest = my_strcat (dest, src + j, i - j);
+ j = i + 1;
+ switch (c) {
+ case '&': dest = my_strcat (dest, "&amp;", 5); break;
+ case '\'': dest = my_strcat (dest, "&apos;", 6); break;
+ case '"': dest = my_strcat (dest, "&quot;", 6); break;
+ case '<': dest = my_strcat (dest, "&lt;", 4); break;
+ case '>': dest = my_strcat (dest, "&gt;", 4); break;
+ }
+ }
+ }
+ if (i - j > 0) dest = my_strcat (dest, src + j, i - j);
+ return dest;
+}
+
+char *
+iks_string (ikstack *s, iks *x)
+{
+ size_t size;
+ int level, dir;
+ iks *y, *z;
+ char *ret, *t;
+
+ if (!x) return NULL;
+
+ if (x->type == IKS_CDATA) {
+ if (s) {
+ return iks_stack_strdup (s, IKS_CDATA_CDATA (x), IKS_CDATA_LEN (x));
+ } else {
+ ret = iks_malloc (IKS_CDATA_LEN (x));
+ memcpy (ret, IKS_CDATA_CDATA (x), IKS_CDATA_LEN (x));
+ return ret;
+ }
+ }
+
+ size = 0;
+ level = 0;
+ dir = 0;
+ y = x;
+ while (1) {
+ if (dir==0) {
+ if (y->type == IKS_TAG) {
+ size++;
+ size += strlen (IKS_TAG_NAME (y));
+ for (z = IKS_TAG_ATTRIBS (y); z; z = z->next) {
+ size += 4 + strlen (IKS_ATTRIB_NAME (z))
+ + escape_size (IKS_ATTRIB_VALUE (z), strlen (IKS_ATTRIB_VALUE (z)));
+ }
+ if (IKS_TAG_CHILDREN (y)) {
+ size++;
+ y = IKS_TAG_CHILDREN (y);
+ level++;
+ continue;
+ } else {
+ size += 2;
+ }
+ } else {
+ size += escape_size (IKS_CDATA_CDATA (y), IKS_CDATA_LEN (y));
+ }
+ }
+ z = y->next;
+ if (z) {
+ if (0 == level) {
+ if (IKS_TAG_CHILDREN (y)) size += 3 + strlen (IKS_TAG_NAME (y));
+ break;
+ }
+ y = z;
+ dir = 0;
+ } else {
+ y = y->parent;
+ level--;
+ if (level >= 0) size += 3 + strlen (IKS_TAG_NAME (y));
+ if (level < 1) break;
+ dir = 1;
+ }
+ }
+
+ if (s) ret = iks_stack_alloc (s, size + 1);
+ else ret = iks_malloc (size + 1);
+
+ if (!ret) return NULL;
+
+ t = ret;
+ level = 0;
+ dir = 0;
+ while (1) {
+ if (dir==0) {
+ if (x->type == IKS_TAG) {
+ *t++ = '<';
+ t = my_strcat (t, IKS_TAG_NAME (x), 0);
+ y = IKS_TAG_ATTRIBS (x);
+ while (y) {
+ *t++ = ' ';
+ t = my_strcat (t, IKS_ATTRIB_NAME (y), 0);
+ *t++ = '=';
+ *t++ = '\'';
+ t = escape (t, IKS_ATTRIB_VALUE (y), strlen (IKS_ATTRIB_VALUE (y)));
+ *t++ = '\'';
+ y = y->next;
+ }
+ if (IKS_TAG_CHILDREN (x)) {
+ *t++ = '>';
+ x = IKS_TAG_CHILDREN (x);
+ level++;
+ continue;
+ } else {
+ *t++ = '/';
+ *t++ = '>';
+ }
+ } else {
+ t = escape (t, IKS_CDATA_CDATA (x), IKS_CDATA_LEN (x));
+ }
+ }
+ y = x->next;
+ if (y) {
+ if (0 == level) {
+ if (IKS_TAG_CHILDREN (x)) {
+ *t++ = '<';
+ *t++ = '/';
+ t = my_strcat (t, IKS_TAG_NAME (x), 0);
+ *t++ = '>';
+ }
+ break;
+ }
+ x = y;
+ dir = 0;
+ } else {
+ x = x->parent;
+ level--;
+ if (level >= 0) {
+ *t++ = '<';
+ *t++ = '/';
+ t = my_strcat (t, IKS_TAG_NAME (x), 0);
+ *t++ = '>';
+ }
+ if (level < 1) break;
+ dir = 1;
+ }
+ }
+ *t = '\0';
+
+ return ret;
+}
+
+/***** Copying *****/
+
+iks *
+iks_copy_within (iks *x, ikstack *s)
+{
+ int level=0, dir=0;
+ iks *copy = NULL;
+ iks *cur = NULL;
+ iks *y;
+
+ while (1) {
+ if (dir == 0) {
+ if (x->type == IKS_TAG) {
+ if (copy == NULL) {
+ copy = iks_new_within (IKS_TAG_NAME (x), s);
+ cur = copy;
+ } else {
+ cur = iks_insert (cur, IKS_TAG_NAME (x));
+ }
+ for (y = IKS_TAG_ATTRIBS (x); y; y = y->next) {
+ iks_insert_attrib (cur, IKS_ATTRIB_NAME (y), IKS_ATTRIB_VALUE (y));
+ }
+ if (IKS_TAG_CHILDREN (x)) {
+ x = IKS_TAG_CHILDREN (x);
+ level++;
+ continue;
+ } else {
+ cur = cur->parent;
+ }
+ } else {
+ iks_insert_cdata (cur, IKS_CDATA_CDATA (x), IKS_CDATA_LEN (x));
+ }
+ }
+ y = x->next;
+ if (y) {
+ if (0 == level) break;
+ x = y;
+ dir = 0;
+ } else {
+ if (level < 2) break;
+ level--;
+ x = x->parent;
+ cur = cur->parent;
+ dir = 1;
+ }
+ }
+ return copy;
+}
+
+iks *
+iks_copy (iks *x)
+{
+ return iks_copy_within (x, iks_stack_new (sizeof (struct iks_tag) * 6, 256));
+}
diff --git a/src/ikstack.c b/src/ikstack.c
new file mode 100644
index 0000000..a1dc654
--- /dev/null
+++ b/src/ikstack.c
@@ -0,0 +1,202 @@
+/* iksemel (XML parser for Jabber)
+** Copyright (C) 2000-2004 Gurer Ozen <madcat@e-kolay.net>
+** This code is free software; you can redistribute it and/or
+** modify it under the terms of GNU Lesser General Public License.
+*/
+
+#include "common.h"
+#include "iksemel.h"
+
+struct align_test { char a; double b; };
+#define DEFAULT_ALIGNMENT ((size_t) ((char *) &((struct align_test *) 0)->b - (char *) 0))
+#define ALIGN_MASK ( DEFAULT_ALIGNMENT - 1 )
+#define MIN_CHUNK_SIZE ( DEFAULT_ALIGNMENT * 8 )
+#define MIN_ALLOC_SIZE DEFAULT_ALIGNMENT
+#define ALIGN(x) ( (x) + (DEFAULT_ALIGNMENT - ( (x) & ALIGN_MASK)) )
+
+typedef struct ikschunk_struct {
+ struct ikschunk_struct *next;
+ size_t size;
+ size_t used;
+ size_t last;
+ char data[4];
+} ikschunk;
+
+struct ikstack_struct {
+ size_t allocated;
+ ikschunk *meta;
+ ikschunk *data;
+};
+
+static ikschunk *
+find_space (ikstack *s, ikschunk *c, size_t size)
+{
+ /* FIXME: dont use *2 after over allocated chunks */
+ while (1) {
+ if (c->size - c->used >= size) return c;
+ if (!c->next) {
+ if ((c->size * 2) > size) size = c->size * 2;
+ c->next = iks_malloc (sizeof (ikschunk) + size);
+ if (!c->next) return NULL;
+ s->allocated += sizeof (ikschunk) + size;
+ c = c->next;
+ c->next = NULL;
+ c->size = size;
+ c->used = 0;
+ c->last = (size_t) -1;
+ return c;
+ }
+ c = c->next;
+ }
+ return NULL;
+}
+
+ikstack *
+iks_stack_new (size_t meta_chunk, size_t data_chunk)
+{
+ ikstack *s;
+ size_t len;
+
+ if (meta_chunk < MIN_CHUNK_SIZE) meta_chunk = MIN_CHUNK_SIZE;
+ if (meta_chunk & ALIGN_MASK) meta_chunk = ALIGN (meta_chunk);
+ if (data_chunk < MIN_CHUNK_SIZE) data_chunk = MIN_CHUNK_SIZE;
+ if (data_chunk & ALIGN_MASK) data_chunk = ALIGN (data_chunk);
+
+ len = sizeof (ikstack) + meta_chunk + data_chunk + (sizeof (ikschunk) * 2);
+ s = iks_malloc (len);
+ if (!s) return NULL;
+ s->allocated = len;
+ s->meta = (ikschunk *) ((char *) s + sizeof (ikstack));
+ s->meta->next = NULL;
+ s->meta->size = meta_chunk;
+ s->meta->used = 0;
+ s->meta->last = (size_t) -1;
+ s->data = (ikschunk *) ((char *) s + sizeof (ikstack) + sizeof (ikschunk) + meta_chunk);
+ s->data->next = NULL;
+ s->data->size = data_chunk;
+ s->data->used = 0;
+ s->data->last = (size_t) -1;
+ return s;
+}
+
+void *
+iks_stack_alloc (ikstack *s, size_t size)
+{
+ ikschunk *c;
+ void *mem;
+
+ if (size < MIN_ALLOC_SIZE) size = MIN_ALLOC_SIZE;
+ if (size & ALIGN_MASK) size = ALIGN (size);
+
+ c = find_space (s, s->meta, size);
+ if (!c) return NULL;
+ mem = c->data + c->used;
+ c->used += size;
+ return mem;
+}
+
+char *
+iks_stack_strdup (ikstack *s, const char *src, size_t len)
+{
+ ikschunk *c;
+ char *dest;
+
+ if (!src) return NULL;
+ if (0 == len) len = strlen (src);
+
+ c = find_space (s, s->data, len + 1);
+ if (!c) return NULL;
+ dest = c->data + c->used;
+ c->last = c->used;
+ c->used += len + 1;
+ memcpy (dest, src, len);
+ dest[len] = '\0';
+ return dest;
+}
+
+char *
+iks_stack_strcat (ikstack *s, char *old, size_t old_len, const char *src, size_t src_len)
+{
+ char *ret;
+ ikschunk *c;
+
+ if (!old) {
+ return iks_stack_strdup (s, src, src_len);
+ }
+ if (0 == old_len) old_len = strlen (old);
+ if (0 == src_len) src_len = strlen (src);
+
+ for (c = s->data; c; c = c->next) {
+ if (c->data + c->last == old) break;
+ }
+ if (!c) {
+ c = find_space (s, s->data, old_len + src_len + 1);
+ if (!c) return NULL;
+ ret = c->data + c->used;
+ c->last = c->used;
+ c->used += old_len + src_len + 1;
+ memcpy (ret, old, old_len);
+ memcpy (ret + old_len, src, src_len);
+ ret[old_len + src_len] = '\0';
+ return ret;
+ }
+
+ if (c->size - c->used > src_len) {
+ ret = c->data + c->last;
+ memcpy (ret + old_len, src, src_len);
+ c->used += src_len;
+ ret[old_len + src_len] = '\0';
+ } else {
+ /* FIXME: decrease c->used before moving string to new place */
+ c = find_space (s, s->data, old_len + src_len + 1);
+ if (!c) return NULL;
+ c->last = c->used;
+ ret = c->data + c->used;
+ memcpy (ret, old, old_len);
+ c->used += old_len;
+ memcpy (c->data + c->used, src, src_len);
+ c->used += src_len;
+ c->data[c->used] = '\0';
+ c->used++;
+ }
+ return ret;
+}
+
+void
+iks_stack_stat (ikstack *s, size_t *allocated, size_t *used)
+{
+ ikschunk *c;
+
+ if (allocated) {
+ *allocated = s->allocated;
+ }
+ if (used) {
+ *used = 0;
+ for (c = s->meta; c; c = c->next) {
+ (*used) += c->used;
+ }
+ for (c = s->data; c; c = c->next) {
+ (*used) += c->used;
+ }
+ }
+}
+
+void
+iks_stack_delete (ikstack *s)
+{
+ ikschunk *c, *tmp;
+
+ c = s->meta->next;
+ while (c) {
+ tmp = c->next;
+ iks_free (c);
+ c = tmp;
+ }
+ c = s->data->next;
+ while (c) {
+ tmp = c->next;
+ iks_free (c);
+ c = tmp;
+ }
+ iks_free (s);
+}
diff --git a/src/io-posix.c b/src/io-posix.c
new file mode 100644
index 0000000..a46fdfe
--- /dev/null
+++ b/src/io-posix.c
@@ -0,0 +1,137 @@
+/* iksemel (XML parser for Jabber)
+** Copyright (C) 2004 Gurer Ozen <madcat@e-kolay.net>
+** This code is free software; you can redistribute it and/or
+** modify it under the terms of GNU Lesser General Public License.
+*/
+
+#include "common.h"
+#include "iksemel.h"
+
+#ifdef _WIN32
+#include <winsock.h>
+#else
+#include <netdb.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#endif
+
+static void
+io_close (void *socket)
+{
+ int sock = (int) socket;
+#ifdef _WIN32
+ closesocket (sock);
+#else
+ close (sock);
+#endif
+}
+
+static int
+io_connect (iksparser *prs, void **socketptr, const char *server, int port)
+{
+ int sock = -1;
+ int tmp;
+#ifdef HAVE_GETADDRINFO
+ struct addrinfo hints;
+ struct addrinfo *addr_res, *addr_ptr;
+ char port_str[6];
+ int err = 0;
+
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = 0;
+ hints.ai_addrlen = 0;
+ hints.ai_canonname = NULL;
+ hints.ai_addr = NULL;
+ hints.ai_next = NULL;
+ sprintf (port_str, "%i", port);
+
+ if (getaddrinfo (server, port_str, &hints, &addr_res) != 0)
+ return IKS_NET_NODNS;
+
+ addr_ptr = addr_res;
+ while (addr_ptr) {
+ err = IKS_NET_NOSOCK;
+ sock = socket (addr_ptr->ai_family, addr_ptr->ai_socktype, addr_ptr->ai_protocol);
+ if (sock != -1) {
+ err = IKS_NET_NOCONN;
+ tmp = connect (sock, addr_ptr->ai_addr, addr_ptr->ai_addrlen);
+ if (tmp == 0) break;
+ io_close ((void *) sock);
+ sock = -1;
+ }
+ addr_ptr = addr_ptr->ai_next;
+ }
+ freeaddrinfo (addr_res);
+
+ if (sock == -1) return err;
+#else
+ struct hostent *host;
+ struct sockaddr_in sin;
+
+ host = gethostbyname (server);
+ if (!host) return IKS_NET_NODNS;
+
+ memcpy (&sin.sin_addr, host->h_addr, host->h_length);
+ sin.sin_family = host->h_addrtype;
+ sin.sin_port = htons (port);
+ sock = socket (host->h_addrtype, SOCK_STREAM, 0);
+ if (sock == -1) return IKS_NET_NOSOCK;
+
+ tmp = connect (sock, (struct sockaddr *)&sin, sizeof (struct sockaddr_in));
+ if (tmp != 0) {
+ io_close ((void *) sock);
+ return IKS_NET_NOCONN;
+ }
+#endif
+
+ *socketptr = (void *) sock;
+
+ return IKS_OK;
+}
+
+static int
+io_send (void *socket, const char *data, size_t len)
+{
+ int sock = (int) socket;
+
+ if (send (sock, data, len, 0) == -1) return IKS_NET_RWERR;
+ return IKS_OK;
+}
+
+static int
+io_recv (void *socket, char *buffer, size_t buf_len, int timeout)
+{
+ int sock = (int) socket;
+ fd_set fds;
+ struct timeval tv, *tvptr;
+ int len;
+
+ tv.tv_sec = 0;
+ tv.tv_usec = 0;
+
+ FD_ZERO (&fds);
+ FD_SET (sock, &fds);
+ tv.tv_sec = timeout;
+ if (timeout != -1) tvptr = &tv; else tvptr = NULL;
+ if (select (sock + 1, &fds, NULL, NULL, tvptr) > 0) {
+ len = recv (sock, buffer, buf_len, 0);
+ if (len > 0) {
+ return len;
+ } else if (len <= 0) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
+ikstransport iks_default_transport = {
+ IKS_TRANSPORT_V1,
+ io_connect,
+ io_send,
+ io_recv,
+ io_close,
+ NULL
+};
diff --git a/src/jabber.c b/src/jabber.c
new file mode 100644
index 0000000..9143751
--- /dev/null
+++ b/src/jabber.c
@@ -0,0 +1,330 @@
+/* iksemel (XML parser for Jabber)
+** Copyright (C) 2000-2003 Gurer Ozen <madcat@e-kolay.net>
+** This code is free software; you can redistribute it and/or
+** modify it under the terms of GNU Lesser General Public License.
+*/
+
+#include "common.h"
+#include "iksemel.h"
+
+iksid *
+iks_id_new (ikstack *s, const char *jid)
+{
+ iksid *id;
+ char *src, *tmp;
+
+/* FIXME: add jabber id validity checks to this function */
+/* which characters are allowed in id parts? */
+
+ if (!jid) return NULL;
+ id = iks_stack_alloc (s, sizeof (iksid));
+ if (!id) return NULL;
+ memset (id, 0, sizeof (iksid));
+
+ /* skip scheme */
+ if (strncmp ("jabber:", jid, 7) == 0) jid += 7;
+
+ id->full = iks_stack_strdup (s, jid, 0);
+ src = id->full;
+
+ /* split resource */
+ tmp = strchr (src, '/');
+ if (tmp) {
+ id->partial = iks_stack_strdup (s, src, tmp - src);
+ id->resource = tmp + 1;
+ src = id->partial;
+ } else {
+ id->partial = src;
+ }
+
+ /* split user */
+ tmp = strchr (src, '@');
+ if (tmp) {
+ id->user = iks_stack_strdup (s, src, tmp - src);
+ src = ++tmp;
+ }
+
+ id->server = src;
+
+ return id;
+}
+
+int
+iks_id_cmp (iksid *a, iksid *b, int parts)
+{
+ int diff;
+
+ if (!a || !b) return (IKS_ID_RESOURCE | IKS_ID_USER | IKS_ID_SERVER);
+ diff = 0;
+ if (parts & IKS_ID_RESOURCE && !(!a->resource && !b->resource) && iks_strcmp (a->resource, b->resource) != 0)
+ diff += IKS_ID_RESOURCE;
+ if (parts & IKS_ID_USER && !(!a->user && !b->user) && iks_strcasecmp (a->user, b->user) != 0)
+ diff += IKS_ID_USER;
+ if (parts & IKS_ID_SERVER && !(!a->server && !b->server) && iks_strcmp (a->server, b->server) != 0)
+ diff += IKS_ID_SERVER;
+ return diff;
+}
+
+ikspak *
+iks_packet (iks *x)
+{
+ ikspak *pak;
+ ikstack *s;
+ char *tmp;
+
+ s = iks_stack (x);
+ pak = iks_stack_alloc (s, sizeof (ikspak));
+ if (!pak) return NULL;
+ memset (pak, 0, sizeof (ikspak));
+ pak->x = x;
+ tmp = iks_find_attrib (x, "from");
+ if (tmp) pak->from = iks_id_new (s, tmp);
+ pak->id = iks_find_attrib (x, "id");
+
+ tmp = iks_find_attrib (x, "type");
+ if (strcmp (iks_name (x), "message") == 0) {
+ pak->type = IKS_PAK_MESSAGE;
+ if (tmp) {
+ if (strcmp (tmp, "chat") == 0)
+ pak->subtype = IKS_TYPE_CHAT;
+ else if (strcmp (tmp, "groupchat") == 0)
+ pak->subtype = IKS_TYPE_GROUPCHAT;
+ else if (strcmp (tmp, "headline") == 0)
+ pak->subtype = IKS_TYPE_HEADLINE;
+ else if (strcmp (tmp, "error") == 0)
+ pak->subtype = IKS_TYPE_ERROR;
+ }
+ } else if (strcmp (iks_name (x), "presence") == 0) {
+ pak->type = IKS_PAK_S10N;
+ if (tmp) {
+ if (strcmp (tmp, "unavailable") == 0) {
+ pak->type = IKS_PAK_PRESENCE;
+ pak->subtype = IKS_TYPE_UNAVAILABLE;
+ pak->show = IKS_SHOW_UNAVAILABLE;
+ } else if (strcmp (tmp, "probe") == 0) {
+ pak->type = IKS_PAK_PRESENCE;
+ pak->subtype = IKS_TYPE_PROBE;
+ } else if(strcmp(tmp, "subscribe") == 0)
+ pak->subtype = IKS_TYPE_SUBSCRIBE;
+ else if(strcmp(tmp, "subscribed") == 0)
+ pak->subtype = IKS_TYPE_SUBSCRIBED;
+ else if(strcmp(tmp, "unsubscribe") == 0)
+ pak->subtype = IKS_TYPE_UNSUBSCRIBE;
+ else if(strcmp(tmp, "unsubscribed") == 0)
+ pak->subtype = IKS_TYPE_UNSUBSCRIBED;
+ else if(strcmp(tmp, "error") == 0)
+ pak->subtype = IKS_TYPE_ERROR;
+ } else {
+ pak->type = IKS_PAK_PRESENCE;
+ pak->subtype = IKS_TYPE_AVAILABLE;
+ tmp = iks_find_cdata (x, "show");
+ pak->show = IKS_SHOW_AVAILABLE;
+ if (tmp) {
+ if (strcmp (tmp, "chat") == 0)
+ pak->show = IKS_SHOW_CHAT;
+ else if (strcmp (tmp, "away") == 0)
+ pak->show = IKS_SHOW_AWAY;
+ else if (strcmp (tmp, "xa") == 0)
+ pak->show = IKS_SHOW_XA;
+ else if (strcmp (tmp, "dnd") == 0)
+ pak->show = IKS_SHOW_DND;
+ }
+ }
+ } else if (strcmp (iks_name (x), "iq") == 0) {
+ iks *q;
+ pak->type = IKS_PAK_IQ;
+ if (tmp) {
+ if (strcmp (tmp, "get") == 0)
+ pak->subtype = IKS_TYPE_GET;
+ else if (strcmp (tmp, "set") == 0)
+ pak->subtype = IKS_TYPE_SET;
+ else if (strcmp (tmp, "result") == 0)
+ pak->subtype = IKS_TYPE_RESULT;
+ else if (strcmp (tmp, "error") == 0)
+ pak->subtype = IKS_TYPE_ERROR;
+ }
+ for (q = iks_child (x); q; q = iks_next (q)) {
+ if (IKS_TAG == iks_type (q)) {
+ char *ns;
+ ns = iks_find_attrib (q, "xmlns");
+ if (ns) {
+ pak->query = q;
+ pak->ns = ns;
+ break;
+ }
+ }
+ }
+ }
+ return pak;
+}
+
+iks *
+iks_make_auth (iksid *id, const char *pass, const char *sid)
+{
+ iks *x, *y;
+
+ x = iks_new ("iq");
+ iks_insert_attrib (x, "type", "set");
+ y = iks_insert (x, "query");
+ iks_insert_attrib (y, "xmlns", IKS_NS_AUTH);
+ iks_insert_cdata (iks_insert (y, "username"), id->user, 0);
+ iks_insert_cdata (iks_insert (y, "resource"), id->resource, 0);
+ if(sid) {
+ char buf[41];
+ iksha *sha;
+ sha = iks_sha_new ();
+ iks_sha_hash (sha, (const unsigned char*)sid, strlen (sid), 0);
+ iks_sha_hash (sha, (const unsigned char*)pass, strlen (pass), 1);
+ iks_sha_print (sha, buf);
+ iks_sha_delete (sha);
+ iks_insert_cdata (iks_insert (y, "digest"), buf, 40);
+ } else {
+ iks_insert_cdata (iks_insert (y, "password"), pass, 0);
+ }
+ return x;
+}
+
+iks *
+iks_make_msg (enum iksubtype type, const char *to, const char *body)
+{
+ iks *x;
+ char *t = NULL;
+
+ x = iks_new ("message");
+ switch (type) {
+ case IKS_TYPE_CHAT: t = "chat"; break;
+ case IKS_TYPE_GROUPCHAT: t = "groupchat"; break;
+ case IKS_TYPE_HEADLINE: t = "headline"; break;
+ default: break;
+ }
+ if (t) iks_insert_attrib (x, "type", t);
+ if (to) iks_insert_attrib (x, "to", to);
+ if (body) iks_insert_cdata (iks_insert (x, "body"), body, 0);
+ return x;
+}
+
+iks *
+iks_make_s10n (enum iksubtype type, const char *to, const char *msg)
+{
+ iks *x;
+ char *t;
+
+ x = iks_new ("presence");
+ switch (type) {
+ case IKS_TYPE_SUBSCRIBE: t = "subscribe"; break;
+ case IKS_TYPE_SUBSCRIBED: t = "subscribed"; break;
+ case IKS_TYPE_UNSUBSCRIBE: t = "unsubscribe"; break;
+ case IKS_TYPE_UNSUBSCRIBED: t = "unsubscribed"; break;
+ case IKS_TYPE_PROBE: t = "probe"; break;
+ default: t = NULL; break;
+ }
+ if (t) iks_insert_attrib (x, "type", t);
+ if (to) iks_insert_attrib (x, "to", to);
+ if (msg) iks_insert_cdata(iks_insert (x, "status"), msg, 0);
+ return x;
+}
+
+iks *
+iks_make_pres (enum ikshowtype show, const char *status)
+{
+ iks *x;
+ char *t;
+
+ x = iks_new ("presence");
+ switch (show) {
+ case IKS_SHOW_CHAT: t = "chat"; break;
+ case IKS_SHOW_AWAY: t = "away"; break;
+ case IKS_SHOW_XA: t = "xa"; break;
+ case IKS_SHOW_DND: t = "dnd"; break;
+ case IKS_SHOW_UNAVAILABLE:
+ t = NULL;
+ iks_insert_attrib (x, "type", "unavailable");
+ break;
+ default: t = NULL; break;
+ }
+ if (t) iks_insert_cdata (iks_insert (x, "show"), t, 0);
+ if (status) iks_insert_cdata(iks_insert (x, "status"), status, 0);
+ return x;
+}
+
+iks *
+iks_make_iq (enum iksubtype type, const char *xmlns)
+{
+ iks *x;
+ char *t = NULL;
+
+ x = iks_new ("iq");
+ switch (type) {
+ case IKS_TYPE_GET: t = "get"; break;
+ case IKS_TYPE_SET: t = "set"; break;
+ case IKS_TYPE_RESULT: t = "result"; break;
+ case IKS_TYPE_ERROR: t = "error"; break;
+ default: break;
+ }
+ if (t) iks_insert_attrib (x, "type", t);
+ iks_insert_attrib (iks_insert (x, "query"), "xmlns", xmlns);
+
+ return x;
+}
+
+iks *
+iks_make_resource_bind (iksid *id)
+{
+ iks *x, *y, *z;
+
+ x = iks_new("iq");
+ iks_insert_attrib(x, "type", "set");
+ y = iks_insert(x, "bind");
+ iks_insert_attrib(y, "xmlns", IKS_NS_XMPP_BIND);
+ if (id->resource && iks_strcmp(id->resource, "")) {
+ z = iks_insert(y, "resource");
+ iks_insert_cdata(z, id->resource, 0);
+ }
+ return x;
+}
+
+iks *
+iks_make_session (void)
+{
+ iks *x, *y;
+
+ x = iks_new ("iq");
+ iks_insert_attrib (x, "type", "set");
+ y = iks_insert (x, "session");
+ iks_insert_attrib (y, "xmlns", IKS_NS_XMPP_SESSION);
+ return x;
+}
+
+static int
+iks_sasl_mechanisms (iks *x)
+{
+ int sasl_mech = 0;
+
+ while (x) {
+ if (!iks_strcmp(iks_cdata(iks_child(x)), "DIGEST-MD5"))
+ sasl_mech |= IKS_STREAM_SASL_MD5;
+ else if (!iks_strcmp(iks_cdata(iks_child(x)), "PLAIN"))
+ sasl_mech |= IKS_STREAM_SASL_PLAIN;
+ x = iks_next_tag(x);
+ }
+ return sasl_mech;
+}
+
+int
+iks_stream_features (iks *x)
+{
+ int features = 0;
+
+ if (iks_strcmp(iks_name(x), "stream:features"))
+ return 0;
+ for (x = iks_child(x); x; x = iks_next_tag(x))
+ if (!iks_strcmp(iks_name(x), "starttls"))
+ features |= IKS_STREAM_STARTTLS;
+ else if (!iks_strcmp(iks_name(x), "bind"))
+ features |= IKS_STREAM_BIND;
+ else if (!iks_strcmp(iks_name(x), "session"))
+ features |= IKS_STREAM_SESSION;
+ else if (!iks_strcmp(iks_name(x), "mechanisms"))
+ features |= iks_sasl_mechanisms(iks_child(x));
+ return features;
+}
diff --git a/src/md5.c b/src/md5.c
new file mode 100644
index 0000000..11af2d8
--- /dev/null
+++ b/src/md5.c
@@ -0,0 +1,189 @@
+/* iksemel (XML parser for Jabber)
+** Copyright (C) 2000-2003 Gurer Ozen <madcat@e-kolay.net>
+** This code is free software; you can redistribute it and/or
+** modify it under the terms of GNU Lesser General Public License.
+*/
+
+#include "common.h"
+#include "iksemel.h"
+
+#define GET_UINT32(n,b,i) { \
+ (n) = ( (unsigned long int) (b)[(i) ] ) \
+ | ( (unsigned long int) (b)[(i) + 1] << 8 ) \
+ | ( (unsigned long int) (b)[(i) + 2] << 16 ) \
+ | ( (unsigned long int) (b)[(i) + 3] << 24 ); \
+}
+
+#define PUT_UINT32(n,b,i) { \
+ (b)[(i) ] = (unsigned char) ( (n) ); \
+ (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
+ (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
+ (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
+}
+
+#define F(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
+
+#define G(x,y,z) ((y) ^ ((z) & ((x) ^ (y))))
+
+#define H(x,y,z) ((x) ^ (y) ^ (z))
+
+#define I(x,y,z) ((y) ^ ((x) | ~(z)))
+
+#define S(x,n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n))))
+
+#define P(r,i,f,k,s,t) { \
+ r[i] += f(r[((i)+1)%4],r[((i)+2)%4],r[((i)+3)%4]) + X[k] + t; \
+ r[i] = S(r[i],s) + r[((i)+1)%4]; \
+}
+
+struct iksmd5_struct {
+ unsigned long int total[2];
+ unsigned long int state[4];
+ unsigned char buffer[64];
+ unsigned char blen;
+};
+
+static const unsigned long int T[] =
+ { 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
+ 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
+ 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
+ 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
+ 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
+ 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
+ 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
+ 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
+ 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
+ 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
+ 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
+ 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
+ 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
+ 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
+ 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
+ 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 };
+
+static void iks_md5_compute(iksmd5 *md5);
+
+void iks_md5_reset(iksmd5 *md5)
+{
+ memset(md5, 0, sizeof(iksmd5));
+ md5->state[0] = 0x67452301;
+ md5->state[1] = 0xEFCDAB89;
+ md5->state[2] = 0x98BADCFE;
+ md5->state[3] = 0x10325476;
+}
+
+iksmd5 *iks_md5_new(void)
+{
+ iksmd5 *md5 = malloc(sizeof(iksmd5));
+
+ if (!md5)
+ return NULL;
+ iks_md5_reset(md5);
+ return md5;
+}
+
+void iks_md5_hash(iksmd5 *md5, const unsigned char *data, size_t slen, int finish)
+{
+ int i, j;
+ int len = slen;
+
+ i = (64 - md5->blen);
+ j = (len < i) ? (len) : (i);
+ memcpy(md5->buffer + md5->blen, data, j);
+ md5->blen += j;
+ len -= j;
+ data += j;
+ while (len > 0) {
+ iks_md5_compute(md5);
+ md5->blen = 0;
+ md5->total[0] += 8*64;
+ md5->total[1] += (md5->total[0] < 8*64);
+ j = (len < 64) ? (len) : (64);
+ memcpy(md5->buffer, data, j);
+ md5->blen = j;
+ len -= j;
+ data += j;
+ }
+ if (finish) {
+ md5->total[0] += 8*md5->blen;
+ md5->total[1] += (md5->total[0] < 8*md5->blen);
+ md5->buffer[(md5->blen)++] = 0x80;
+ if (md5->blen > 56) {
+ while (md5->blen < 64)
+ md5->buffer[(md5->blen)++] = 0x00;
+ iks_md5_compute(md5);
+ md5->blen = 0;
+ }
+ while (md5->blen < 56)
+ md5->buffer[(md5->blen)++] = 0x00;
+ PUT_UINT32(md5->total[0], md5->buffer, 56);
+ PUT_UINT32(md5->total[1], md5->buffer, 60);
+ iks_md5_compute(md5);
+ }
+}
+
+void iks_md5_delete(iksmd5 *md5)
+{
+ free(md5);
+}
+
+void iks_md5_digest(iksmd5 *md5, unsigned char *digest)
+{
+ PUT_UINT32(md5->state[0], digest, 0);
+ PUT_UINT32(md5->state[1], digest, 4);
+ PUT_UINT32(md5->state[2], digest, 8);
+ PUT_UINT32(md5->state[3], digest, 12);
+}
+
+void iks_md5_print(iksmd5 *md5, char *buf)
+{
+ int i;
+ unsigned char digest[16];
+
+ iks_md5_digest(md5, digest);
+ for (i = 0; i < 16; i++) {
+ sprintf (buf, "%02x", digest[i]);
+ buf += 2;
+ }
+}
+
+void iks_md5(const char *data, char *buf)
+{
+ iksmd5 *md5 = iks_md5_new();
+
+ iks_md5_hash(md5, (const unsigned char*)data, strlen(data), 1);
+ iks_md5_print(md5, buf);
+ iks_md5_delete(md5);
+}
+
+static void iks_md5_compute(iksmd5 *md5)
+{
+ unsigned long int X[16], R[4];
+ unsigned char RS1[] = { 7, 12 ,17, 22 };
+ unsigned char RS2[] = { 5, 9 ,14, 20 };
+ unsigned char RS3[] = { 4, 11 ,16, 23 };
+ unsigned char RS4[] = { 6, 10 ,15, 21 };
+ int i, j, k, p;
+
+ for (i = 0; i < 16; ++i)
+ GET_UINT32(X[i], md5->buffer, i*4);
+
+ for (i = 0; i < 4; ++i)
+ R[i] = md5->state[i];
+
+ for (i = j = k = 0; i < 16; ++i, j = i%4, k = (k+3)%4)
+ P(R, k, F, i, RS1[j], T[i]);
+
+ for (i = j = k = 0, p = 1; i < 16; ++i, j = i%4, k = (k+3)%4, p = (p+5)%16)
+ P(R, k, G, p, RS2[j], T[i+16]);
+
+ for (i = j = k = 0, p = 5; i < 16; ++i, j = i%4, k = (k+3)%4, p = (p+3)%16)
+ P(R, k, H, p, RS3[j], T[i+32]);
+
+ for (i = j = k = p = 0; i < 16; ++i, j = i%4, k = (k+3)%4, p = (p+7)%16)
+ P(R, k, I, p, RS4[j], T[i+48]);
+
+ for (i = 0; i < 4; ++i)
+ md5->state[i] += R[i];
+}
+
diff --git a/src/sax.c b/src/sax.c
new file mode 100644
index 0000000..cb3caef
--- /dev/null
+++ b/src/sax.c
@@ -0,0 +1,634 @@
+/* iksemel (XML parser for Jabber)
+** Copyright (C) 2000-2004 Gurer Ozen <madcat@e-kolay.net>
+** This code is free software; you can redistribute it and/or
+** modify it under the terms of GNU Lesser General Public License.
+*/
+
+#include "common.h"
+#include "iksemel.h"
+
+enum cons_e {
+ C_CDATA = 0,
+ C_TAG_START,
+ C_TAG,
+ C_TAG_END,
+ C_ATTRIBUTE,
+ C_ATTRIBUTE_1,
+ C_ATTRIBUTE_2,
+ C_VALUE,
+ C_VALUE_APOS,
+ C_VALUE_QUOT,
+ C_WHITESPACE,
+ C_ENTITY,
+ C_COMMENT,
+ C_COMMENT_1,
+ C_COMMENT_2,
+ C_COMMENT_3,
+ C_MARKUP,
+ C_MARKUP_1,
+ C_SECT,
+ C_SECT_CDATA,
+ C_SECT_CDATA_1,
+ C_SECT_CDATA_2,
+ C_SECT_CDATA_3,
+ C_SECT_CDATA_4,
+ C_SECT_CDATA_C,
+ C_SECT_CDATA_E,
+ C_SECT_CDATA_E2,
+ C_PI
+};
+
+/* if you add a variable here, dont forget changing iks_parser_reset */
+struct iksparser_struct {
+ ikstack *s;
+ void *user_data;
+ iksTagHook *tagHook;
+ iksCDataHook *cdataHook;
+ iksDeleteHook *deleteHook;
+ /* parser context */
+ char *stack;
+ size_t stack_pos;
+ size_t stack_max;
+
+ enum cons_e context;
+ enum cons_e oldcontext;
+
+ char *tag_name;
+ enum ikstagtype tagtype;
+
+ unsigned int attmax;
+ unsigned int attcur;
+ int attflag;
+ char **atts;
+ int valflag;
+
+ unsigned int entpos;
+ char entity[8];
+
+ unsigned long nr_bytes;
+ unsigned long nr_lines;
+
+ int uni_max;
+ int uni_len;
+};
+
+iksparser *
+iks_sax_new (void *user_data, iksTagHook *tagHook, iksCDataHook *cdataHook)
+{
+ iksparser *prs;
+
+ prs = iks_malloc (sizeof (iksparser));
+ if (NULL == prs) return NULL;
+ memset (prs, 0, sizeof (iksparser));
+ prs->user_data = user_data;
+ prs->tagHook = tagHook;
+ prs->cdataHook = cdataHook;
+ return prs;
+}
+
+iksparser *
+iks_sax_extend (ikstack *s, void *user_data, iksTagHook *tagHook, iksCDataHook *cdataHook, iksDeleteHook *deleteHook)
+{
+ iksparser *prs;
+
+ prs = iks_stack_alloc (s, sizeof (iksparser));
+ if (NULL == prs) return NULL;
+ memset (prs, 0, sizeof (iksparser));
+ prs->s = s;
+ prs->user_data = user_data;
+ prs->tagHook = tagHook;
+ prs->cdataHook = cdataHook;
+ prs->deleteHook = deleteHook;
+ return prs;
+}
+
+ikstack *
+iks_parser_stack (iksparser *prs)
+{
+ return prs->s;
+}
+
+void *
+iks_user_data (iksparser *prs)
+{
+ return prs->user_data;
+}
+
+unsigned long
+iks_nr_bytes (iksparser *prs)
+{
+ return prs->nr_bytes;
+}
+
+unsigned long
+iks_nr_lines (iksparser *prs)
+{
+ return prs->nr_lines;
+}
+
+#define IS_WHITESPACE(x) ' ' == (x) || '\t' == (x) || '\r' == (x) || '\n' == (x)
+#define NOT_WHITESPACE(x) ' ' != (x) && '\t' != (x) && '\r' != (x) && '\n' != (x)
+
+static int
+stack_init (iksparser *prs)
+{
+ prs->stack = iks_malloc (128);
+ if (!prs->stack) return 0;
+ prs->stack_max = 128;
+ prs->stack_pos = 0;
+ return 1;
+}
+
+static int
+stack_expand (iksparser *prs, int len)
+{
+ size_t need;
+ off_t diff;
+ char *tmp;
+ need = len - (prs->stack_max - prs->stack_pos);
+ if (need < prs->stack_max) {
+ need = prs->stack_max * 2;
+ } else {
+ /* need x 1.2 for integer only archs like ARM */
+ need = prs->stack_max + ( (need * 6) / 5);
+ }
+ tmp = iks_malloc (need);
+ if (!tmp) return 0;
+ diff = tmp - prs->stack;
+ memcpy (tmp, prs->stack, prs->stack_max);
+ iks_free (prs->stack);
+ prs->stack = tmp;
+ prs->stack_max = need;
+ prs->tag_name += diff;
+ if (prs->attflag != 0) {
+ int i = 0;
+ while (i < (prs->attmax * 2)) {
+ if (prs->atts[i]) prs->atts[i] += diff;
+ i++;
+ }
+ }
+ return 1;
+}
+
+#define STACK_INIT \
+ if (NULL == prs->stack && 0 == stack_init (prs)) return IKS_NOMEM
+
+#define STACK_PUSH_START (prs->stack + prs->stack_pos)
+
+#define STACK_PUSH(buf,len) \
+{ \
+ char *sbuf = (buf); \
+ size_t slen = (len); \
+ if (prs->stack_max - prs->stack_pos <= slen) { \
+ if (0 == stack_expand (prs, slen)) return IKS_NOMEM; \
+ } \
+ memcpy (prs->stack + prs->stack_pos, sbuf, slen); \
+ prs->stack_pos += slen; \
+}
+
+#define STACK_PUSH_END \
+{ \
+ if (prs->stack_pos >= prs->stack_max) { \
+ if (0 == stack_expand (prs, 1)) return IKS_NOMEM; \
+ } \
+ prs->stack[prs->stack_pos] = '\0'; \
+ prs->stack_pos++; \
+}
+
+static enum ikserror
+sax_core (iksparser *prs, char *buf, int len)
+{
+ enum ikserror err;
+ int pos = 0, old = 0, re, stack_old = -1;
+ unsigned char c;
+
+ while (pos < len) {
+ re = 0;
+ c = buf[pos];
+ if (0 == c || 0xFE == c || 0xFF == c) return IKS_BADXML;
+ if (prs->uni_max) {
+ if ((c & 0xC0) != 0x80) return IKS_BADXML;
+ prs->uni_len++;
+ if (prs->uni_len == prs->uni_max) prs->uni_max = 0;
+ goto cont;
+ } else {
+ if (c & 0x80) {
+ unsigned char mask;
+ if ((c & 0x60) == 0x40) {
+ prs->uni_max = 2;
+ mask = 0x1F;
+ } else if ((c & 0x70) == 0x60) {
+ prs->uni_max = 3;
+ mask = 0x0F;
+ } else if ((c & 0x78) == 0x70) {
+ prs->uni_max = 4;
+ mask = 0x07;
+ } else if ((c & 0x7C) == 0x78) {
+ prs->uni_max = 5;
+ mask = 0x03;
+ } else if ((c & 0x7E) == 0x7C) {
+ prs->uni_max = 6;
+ mask = 0x01;
+ } else {
+ return IKS_BADXML;
+ }
+ if ((c & mask) == 0) return IKS_BADXML;
+ prs->uni_len = 1;
+ if (stack_old == -1
+ && (prs->context == C_TAG
+ || prs->context == C_ATTRIBUTE_1
+ || prs->context == C_VALUE_APOS
+ || prs->context == C_VALUE_QUOT)) stack_old = pos;
+ goto cont;
+ }
+ }
+
+ switch (prs->context) {
+ case C_CDATA:
+ if ('&' == c) {
+ if (old < pos && prs->cdataHook) {
+ err = prs->cdataHook (prs->user_data, &buf[old], pos - old);
+ if (IKS_OK != err) return err;
+ }
+ prs->context = C_ENTITY;
+ prs->entpos = 0;
+ break;
+ }
+ if ('<' == c) {
+ if (old < pos && prs->cdataHook) {
+ err = prs->cdataHook (prs->user_data, &buf[old], pos - old);
+ if (IKS_OK != err) return err;
+ }
+ STACK_INIT;
+ prs->tag_name = STACK_PUSH_START;
+ if (!prs->tag_name) return IKS_NOMEM;
+ prs->context = C_TAG_START;
+ }
+ break;
+
+ case C_TAG_START:
+ prs->context = C_TAG;
+ if ('/' == c) {
+ prs->tagtype = IKS_CLOSE;
+ break;
+ }
+ if ('?' == c) {
+ prs->context = C_PI;
+ break;
+ }
+ if ('!' == c) {
+ prs->context = C_MARKUP;
+ break;
+ }
+ prs->tagtype = IKS_OPEN;
+ stack_old = pos;
+ break;
+
+ case C_TAG:
+ if (IS_WHITESPACE(c)) {
+ if (IKS_CLOSE == prs->tagtype)
+ prs->oldcontext = C_TAG_END;
+ else
+ prs->oldcontext = C_ATTRIBUTE;
+ prs->context = C_WHITESPACE;
+ if (stack_old != -1) STACK_PUSH (buf + stack_old, pos - stack_old);
+ stack_old = -1;
+ STACK_PUSH_END;
+ break;
+ }
+ if ('/' == c) {
+ if (IKS_CLOSE == prs->tagtype) return IKS_BADXML;
+ prs->tagtype = IKS_SINGLE;
+ prs->context = C_TAG_END;
+ if (stack_old != -1) STACK_PUSH (buf + stack_old, pos - stack_old);
+ stack_old = -1;
+ STACK_PUSH_END;
+ break;
+ }
+ if ('>' == c) {
+ prs->context = C_TAG_END;
+ if (stack_old != -1) STACK_PUSH (buf + stack_old, pos - stack_old);
+ stack_old = -1;
+ STACK_PUSH_END;
+ re = 1;
+ break;
+ }
+ if (stack_old == -1) stack_old = pos;
+ break;
+
+ case C_TAG_END:
+ if (c != '>') return IKS_BADXML;
+ if (prs->tagHook) {
+ char **tmp;
+ if (prs->attcur == 0) tmp = NULL; else tmp = prs->atts;
+ err = prs->tagHook (prs->user_data, prs->tag_name, tmp, prs->tagtype);
+ if (IKS_OK != err) return err;
+ }
+ prs->stack_pos = 0;
+ stack_old = -1;
+ prs->attcur = 0;
+ prs->attflag = 0;
+ prs->context = C_CDATA;
+ old = pos + 1;
+ break;
+
+ case C_ATTRIBUTE:
+ if ('/' == c) {
+ prs->tagtype = IKS_SINGLE;
+ prs->context = C_TAG_END;
+ break;
+ }
+ if ('>' == c) {
+ prs->context = C_TAG_END;
+ re = 1;
+ break;
+ }
+ if (!prs->atts) {
+ prs->attmax = 12;
+ prs->atts = iks_malloc (sizeof(char *) * 2 * 12);
+ if (!prs->atts) return IKS_NOMEM;
+ memset (prs->atts, 0, sizeof(char *) * 2 * 12);
+ prs->attcur = 0;
+ } else {
+ if (prs->attcur >= (prs->attmax * 2)) {
+ void *tmp;
+ prs->attmax += 12;
+ tmp = iks_malloc (sizeof(char *) * 2 * prs->attmax);
+ if (!tmp) return IKS_NOMEM;
+ memset (tmp, 0, sizeof(char *) * 2 * prs->attmax);
+ memcpy (tmp, prs->atts, sizeof(char *) * prs->attcur);
+ free (prs->atts);
+ prs->atts = tmp;
+ }
+ }
+ prs->attflag = 1;
+ prs->atts[prs->attcur] = STACK_PUSH_START;
+ stack_old = pos;
+ prs->context = C_ATTRIBUTE_1;
+ break;
+
+ case C_ATTRIBUTE_1:
+ if ('=' == c) {
+ if (stack_old != -1) STACK_PUSH (buf + stack_old, pos - stack_old);
+ stack_old = -1;
+ STACK_PUSH_END;
+ prs->context = C_VALUE;
+ break;
+ }
+ if (stack_old == -1) stack_old = pos;
+ break;
+
+ case C_ATTRIBUTE_2:
+ if ('/' == c) {
+ prs->tagtype = IKS_SINGLE;
+ prs->atts[prs->attcur] = NULL;
+ prs->context = C_TAG_END;
+ break;
+ }
+ if ('>' == c) {
+ prs->atts[prs->attcur] = NULL;
+ prs->context = C_TAG_END;
+ re = 1;
+ break;
+ }
+ prs->context = C_ATTRIBUTE;
+ re = 1;
+ break;
+
+ case C_VALUE:
+ prs->atts[prs->attcur + 1] = STACK_PUSH_START;
+ if ('\'' == c) {
+ prs->context = C_VALUE_APOS;
+ break;
+ }
+ if ('"' == c) {
+ prs->context = C_VALUE_QUOT;
+ break;
+ }
+ return IKS_BADXML;
+
+ case C_VALUE_APOS:
+ if ('\'' == c) {
+ if (stack_old != -1) STACK_PUSH (buf + stack_old, pos - stack_old);
+ stack_old = -1;
+ STACK_PUSH_END;
+ prs->oldcontext = C_ATTRIBUTE_2;
+ prs->context = C_WHITESPACE;
+ prs->attcur += 2;
+ }
+ if (stack_old == -1) stack_old = pos;
+ break;
+
+ case C_VALUE_QUOT:
+ if ('"' == c) {
+ if (stack_old != -1) STACK_PUSH (buf + stack_old, pos - stack_old);
+ stack_old = -1;
+ STACK_PUSH_END;
+ prs->oldcontext = C_ATTRIBUTE_2;
+ prs->context = C_WHITESPACE;
+ prs->attcur += 2;
+ }
+ if (stack_old == -1) stack_old = pos;
+ break;
+
+ case C_WHITESPACE:
+ if (NOT_WHITESPACE(c)) {
+ prs->context = prs->oldcontext;
+ re = 1;
+ }
+ break;
+
+ case C_ENTITY:
+ if (';' == c) {
+ char hede[2];
+ char t = '?';
+ prs->entity[prs->entpos] = '\0';
+ if (strcmp(prs->entity, "amp") == 0)
+ t = '&';
+ else if (strcmp(prs->entity, "quot") == 0)
+ t = '"';
+ else if (strcmp(prs->entity, "apos") == 0)
+ t = '\'';
+ else if (strcmp(prs->entity, "lt") == 0)
+ t = '<';
+ else if (strcmp(prs->entity, "gt") == 0)
+ t = '>';
+ old = pos + 1;
+ hede[0] = t;
+ if (prs->cdataHook) {
+ err = prs->cdataHook (prs->user_data, &hede[0], 1);
+ if (IKS_OK != err) return err;
+ }
+ prs->context = C_CDATA;
+ } else {
+ prs->entity[prs->entpos++] = buf[pos];
+ if (prs->entpos > 7) return IKS_BADXML;
+ }
+ break;
+
+ case C_COMMENT:
+ if ('-' != c) return IKS_BADXML;
+ prs->context = C_COMMENT_1;
+ break;
+
+ case C_COMMENT_1:
+ if ('-' == c) prs->context = C_COMMENT_2;
+ break;
+
+ case C_COMMENT_2:
+ if ('-' == c)
+ prs->context = C_COMMENT_3;
+ else
+ prs->context = C_COMMENT_1;
+ break;
+
+ case C_COMMENT_3:
+ if ('>' != c) return IKS_BADXML;
+ prs->context = C_CDATA;
+ old = pos + 1;
+ break;
+
+ case C_MARKUP:
+ if ('[' == c) {
+ prs->context = C_SECT;
+ break;
+ }
+ if ('-' == c) {
+ prs->context = C_COMMENT;
+ break;
+ }
+ prs->context = C_MARKUP_1;
+
+ case C_MARKUP_1:
+ if ('>' == c) {
+ old = pos + 1;
+ prs->context = C_CDATA;
+ }
+ break;
+
+ case C_SECT:
+ if ('C' == c) {
+ prs->context = C_SECT_CDATA;
+ break;
+ }
+ return IKS_BADXML;
+
+ case C_SECT_CDATA:
+ if ('D' != c) return IKS_BADXML;
+ prs->context = C_SECT_CDATA_1;
+ break;
+
+ case C_SECT_CDATA_1:
+ if ('A' != c) return IKS_BADXML;
+ prs->context = C_SECT_CDATA_2;
+ break;
+
+ case C_SECT_CDATA_2:
+ if ('T' != c) return IKS_BADXML;
+ prs->context = C_SECT_CDATA_3;
+ break;
+
+ case C_SECT_CDATA_3:
+ if ('A' != c) return IKS_BADXML;
+ prs->context = C_SECT_CDATA_4;
+ break;
+
+ case C_SECT_CDATA_4:
+ if ('[' != c) return IKS_BADXML;
+ old = pos + 1;
+ prs->context = C_SECT_CDATA_C;
+ break;
+
+ case C_SECT_CDATA_C:
+ if (']' == c) {
+ prs->context = C_SECT_CDATA_E;
+ if (prs->cdataHook && old < pos) {
+ err = prs->cdataHook (prs->user_data, &buf[old], pos - old);
+ if (IKS_OK != err) return err;
+ }
+ }
+ break;
+
+ case C_SECT_CDATA_E:
+ if (']' == c) {
+ prs->context = C_SECT_CDATA_E2;
+ } else {
+ if (prs->cdataHook) {
+ err = prs->cdataHook (prs->user_data, "]", 1);
+ if (IKS_OK != err) return err;
+ }
+ old = pos;
+ prs->context = C_SECT_CDATA_C;
+ }
+ break;
+
+ case C_SECT_CDATA_E2:
+ if ('>' == c) {
+ old = pos + 1;
+ prs->context = C_CDATA;
+ } else {
+ if (prs->cdataHook) {
+ err = prs->cdataHook (prs->user_data, "]]", 2);
+ if (IKS_OK != err) return err;
+ }
+ old = pos;
+ prs->context = C_SECT_CDATA_C;
+ }
+ break;
+
+ case C_PI:
+ old = pos + 1;
+ if ('>' == c) prs->context = C_CDATA;
+ break;
+ }
+cont:
+ if (0 == re) {
+ pos++;
+ prs->nr_bytes++;
+ if ('\n' == c) prs->nr_lines++;
+ }
+ }
+
+ if (stack_old != -1)
+ STACK_PUSH (buf + stack_old, pos - stack_old);
+
+ err = IKS_OK;
+ if (prs->cdataHook && (prs->context == C_CDATA || prs->context == C_SECT_CDATA_C) && old < pos)
+ err = prs->cdataHook (prs->user_data, &buf[old], pos - old);
+ return err;
+}
+
+int
+iks_parse (iksparser *prs, const char *data, size_t len, int finish)
+{
+ if (!data) return IKS_OK;
+ if (len == 0) len = strlen (data);
+ return sax_core (prs, (char *) data, len);
+}
+
+void
+iks_parser_reset (iksparser *prs)
+{
+ if (prs->deleteHook) prs->deleteHook (prs->user_data);
+ prs->stack_pos = 0;
+ prs->context = 0;
+ prs->oldcontext = 0;
+ prs->tagtype = 0;
+ prs->attcur = 0;
+ prs->attflag = 0;
+ prs->valflag = 0;
+ prs->entpos = 0;
+ prs->nr_bytes = 0;
+ prs->nr_lines = 0;
+ prs->uni_max = 0;
+ prs->uni_len = 0;
+}
+
+void
+iks_parser_delete (iksparser *prs)
+{
+ if (prs->deleteHook) prs->deleteHook (prs->user_data);
+ if (prs->stack) iks_free (prs->stack);
+ if (prs->atts) iks_free (prs->atts);
+ if (prs->s) iks_stack_delete (prs->s); else iks_free (prs);
+}
diff --git a/src/sha.c b/src/sha.c
new file mode 100644
index 0000000..330e1b0
--- /dev/null
+++ b/src/sha.c
@@ -0,0 +1,152 @@
+/* iksemel (XML parser for Jabber)
+** Copyright (C) 2000-2003 Gurer Ozen <madcat@e-kolay.net>
+** This code is free software; you can redistribute it and/or
+** modify it under the terms of GNU Lesser General Public License.
+*/
+
+#include "common.h"
+#include "iksemel.h"
+
+static void sha_buffer (iksha *sha, const unsigned char *data, int len);
+static void sha_calculate (iksha *sha);
+
+struct iksha_struct {
+ unsigned int hash[5];
+ unsigned int buf[80];
+ int blen;
+ unsigned int lenhi, lenlo;
+};
+
+iksha *
+iks_sha_new (void)
+{
+ iksha *sha;
+
+ sha = iks_malloc (sizeof (iksha));
+ if (!sha) return NULL;
+ iks_sha_reset (sha);
+ return sha;
+}
+
+void
+iks_sha_reset (iksha *sha)
+{
+ memset (sha, 0, sizeof (iksha));
+ sha->hash[0] = 0x67452301;
+ sha->hash[1] = 0xefcdab89;
+ sha->hash[2] = 0x98badcfe;
+ sha->hash[3] = 0x10325476;
+ sha->hash[4] = 0xc3d2e1f0;
+}
+
+void
+iks_sha_hash (iksha *sha, const unsigned char *data, size_t len, int finish)
+{
+ unsigned char pad[8];
+ unsigned char padc;
+
+ if (data && len != 0) sha_buffer (sha, data, len);
+ if (!finish) return;
+
+ pad[0] = (unsigned char)((sha->lenhi >> 24) & 0xff);
+ pad[1] = (unsigned char)((sha->lenhi >> 16) & 0xff);
+ pad[2] = (unsigned char)((sha->lenhi >> 8) & 0xff);
+ pad[3] = (unsigned char)(sha->lenhi & 0xff);
+ pad[4] = (unsigned char)((sha->lenlo >> 24) & 0xff);
+ pad[5] = (unsigned char)((sha->lenlo >> 16) & 0xff);
+ pad[6] = (unsigned char)((sha->lenlo >> 8) & 0xff);
+ pad[7] = (unsigned char)(sha->lenlo & 255);
+
+ padc = 0x80;
+ sha_buffer (sha, &padc, 1);
+
+ padc = 0x00;
+ while (sha->blen != 56)
+ sha_buffer (sha, &padc, 1);
+
+ sha_buffer (sha, pad, 8);
+}
+
+void
+iks_sha_print (iksha *sha, char *hash)
+{
+ int i;
+
+ for (i=0; i<5; i++)
+ {
+ sprintf (hash, "%08x", sha->hash[i]);
+ hash += 8;
+ }
+}
+
+void
+iks_sha_delete (iksha *sha)
+{
+ iks_free (sha);
+}
+
+void
+iks_sha (const char *data, char *hash)
+{
+ iksha *sha;
+
+ sha = iks_sha_new ();
+ iks_sha_hash (sha, (const unsigned char*)data, strlen (data), 1);
+ iks_sha_print (sha, hash);
+ iks_free (sha);
+}
+
+static void
+sha_buffer (iksha *sha, const unsigned char *data, int len)
+{
+ int i;
+
+ for (i=0; i<len; i++) {
+ sha->buf[sha->blen / 4] <<= 8;
+ sha->buf[sha->blen / 4] |= (unsigned int)data[i];
+ if ((++sha->blen) % 64 == 0) {
+ sha_calculate (sha);
+ sha->blen = 0;
+ }
+ sha->lenlo += 8;
+ sha->lenhi += (sha->lenlo < 8);
+ }
+}
+
+#define SRL(x,y) (((x) << (y)) | ((x) >> (32-(y))))
+#define SHA(a,b,f,c) \
+ for (i= (a) ; i<= (b) ; i++) { \
+ TMP = SRL(A,5) + ( (f) ) + E + sha->buf[i] + (c) ; \
+ E = D; \
+ D = C; \
+ C = SRL(B,30); \
+ B = A; \
+ A = TMP; \
+ }
+
+static void
+sha_calculate (iksha *sha)
+{
+ int i;
+ unsigned int A, B, C, D, E, TMP;
+
+ for (i=16; i<80; i++)
+ sha->buf[i] = SRL (sha->buf[i-3] ^ sha->buf[i-8] ^ sha->buf[i-14] ^ sha->buf[i-16], 1);
+
+ A = sha->hash[0];
+ B = sha->hash[1];
+ C = sha->hash[2];
+ D = sha->hash[3];
+ E = sha->hash[4];
+
+ SHA (0, 19, ((C^D)&B)^D, 0x5a827999);
+ SHA (20, 39, B^C^D, 0x6ed9eba1);
+ SHA (40, 59, (B&C)|(D&(B|C)), 0x8f1bbcdc);
+ SHA (60, 79, B^C^D, 0xca62c1d6);
+
+ sha->hash[0] += A;
+ sha->hash[1] += B;
+ sha->hash[2] += C;
+ sha->hash[3] += D;
+ sha->hash[4] += E;
+}
diff --git a/src/stream.c b/src/stream.c
new file mode 100644
index 0000000..6bb316e
--- /dev/null
+++ b/src/stream.c
@@ -0,0 +1,642 @@
+/* iksemel (XML parser for Jabber)
+** Copyright (C) 2000-2007 Gurer Ozen <madcat@e-kolay.net>
+** This code is free software; you can redistribute it and/or
+** modify it under the terms of GNU Lesser General Public License.
+*/
+
+#include "common.h"
+#include "iksemel.h"
+
+#ifdef HAVE_GNUTLS
+#include <gnutls/gnutls.h>
+#endif
+
+#define SF_FOREIGN 1
+#define SF_TRY_SECURE 2
+#define SF_SECURE 4
+
+struct stream_data {
+ iksparser *prs;
+ ikstack *s;
+ ikstransport *trans;
+ char *name_space;
+ void *user_data;
+ const char *server;
+ iksStreamHook *streamHook;
+ iksLogHook *logHook;
+ iks *current;
+ char *buf;
+ void *sock;
+ unsigned int flags;
+ char *auth_username;
+ char *auth_pass;
+#ifdef HAVE_GNUTLS
+ gnutls_session sess;
+ gnutls_certificate_credentials cred;
+#endif
+};
+
+#ifdef HAVE_GNUTLS
+
+static size_t
+tls_push (iksparser *prs, const char *buffer, size_t len)
+{
+ struct stream_data *data = iks_user_data (prs);
+ int ret;
+
+ ret = data->trans->send (data->sock, buffer, len);
+ if (ret) return (size_t) -1;
+ return len;
+}
+
+static size_t
+tls_pull (iksparser *prs, char *buffer, size_t len)
+{
+ struct stream_data *data = iks_user_data (prs);
+ int ret;
+
+ ret = data->trans->recv (data->sock, buffer, len, -1);
+ if (ret == -1) return (size_t) -1;
+ return ret;
+}
+
+static int
+handshake (struct stream_data *data)
+{
+ const int protocol_priority[] = { GNUTLS_TLS1, GNUTLS_SSL3, 0 };
+ const int kx_priority[] = { GNUTLS_KX_RSA, 0 };
+ const int cipher_priority[] = { GNUTLS_CIPHER_3DES_CBC, GNUTLS_CIPHER_ARCFOUR, 0};
+ const int comp_priority[] = { GNUTLS_COMP_ZLIB, GNUTLS_COMP_NULL, 0 };
+ const int mac_priority[] = { GNUTLS_MAC_SHA, GNUTLS_MAC_MD5, 0 };
+ int ret;
+
+ if (gnutls_global_init () != 0)
+ return IKS_NOMEM;
+
+ if (gnutls_certificate_allocate_credentials (&data->cred) < 0)
+ return IKS_NOMEM;
+
+ if (gnutls_init (&data->sess, GNUTLS_CLIENT) != 0) {
+ gnutls_certificate_free_credentials (data->cred);
+ return IKS_NOMEM;
+ }
+ gnutls_protocol_set_priority (data->sess, protocol_priority);
+ gnutls_cipher_set_priority(data->sess, cipher_priority);
+ gnutls_compression_set_priority(data->sess, comp_priority);
+ gnutls_kx_set_priority(data->sess, kx_priority);
+ gnutls_mac_set_priority(data->sess, mac_priority);
+ gnutls_credentials_set (data->sess, GNUTLS_CRD_CERTIFICATE, data->cred);
+
+ gnutls_transport_set_push_function (data->sess, (gnutls_push_func) tls_push);
+ gnutls_transport_set_pull_function (data->sess, (gnutls_pull_func) tls_pull);
+ gnutls_transport_set_ptr (data->sess, data->prs);
+
+ ret = gnutls_handshake (data->sess);
+ if (ret != 0) {
+ gnutls_deinit (data->sess);
+ gnutls_certificate_free_credentials (data->cred);
+ return IKS_NET_TLSFAIL;
+ }
+
+ data->flags &= (~SF_TRY_SECURE);
+ data->flags |= SF_SECURE;
+
+ iks_send_header (data->prs, data->server);
+
+ return IKS_OK;
+}
+#endif
+
+static void
+insert_attribs (iks *x, char **atts)
+{
+ if (atts) {
+ int i = 0;
+ while (atts[i]) {
+ iks_insert_attrib (x, atts[i], atts[i+1]);
+ i += 2;
+ }
+ }
+}
+
+#define CNONCE_LEN 4
+
+static void
+parse_digest (char *message, const char *key, char **value_ptr, char **value_end_ptr)
+{
+ char *t;
+
+ *value_ptr = NULL;
+ *value_end_ptr = NULL;
+
+ t = strstr(message, key);
+ if (t) {
+ t += strlen(key);
+ *value_ptr = t;
+ while (t[0] != '\0') {
+ if (t[0] != '\\' && t[1] == '"') {
+ ++t;
+ *value_end_ptr = t;
+ return;
+ }
+ ++t;
+ }
+ }
+}
+
+static iks *
+make_sasl_response (struct stream_data *data, char *message)
+{
+ iks *x = NULL;
+ char *realm, *realm_end;
+ char *nonce, *nonce_end;
+ char cnonce[CNONCE_LEN*8 + 1];
+ iksmd5 *md5;
+ unsigned char a1_h[16], a1[33], a2[33], response_value[33];
+ char *response, *response_coded;
+ int i;
+
+ parse_digest(message, "realm=\"", &realm, &realm_end);
+ parse_digest(message, "nonce=\"", &nonce, &nonce_end);
+
+ /* nonce is necessary for auth */
+ if (!nonce || !nonce_end) return NULL;
+ *nonce_end = '\0';
+
+ /* if no realm is given use the server hostname */
+ if (realm) {
+ if (!realm_end) return NULL;
+ *realm_end = '\0';
+ } else {
+ realm = (char *) data->server;
+ }
+
+ /* generate random client challenge */
+ for (i = 0; i < CNONCE_LEN; ++i)
+ sprintf (cnonce + i*8, "%08x", rand());
+
+ md5 = iks_md5_new();
+ if (!md5) return NULL;
+
+ iks_md5_hash (md5, (const unsigned char*)data->auth_username, iks_strlen (data->auth_username), 0);
+ iks_md5_hash (md5, (const unsigned char*)":", 1, 0);
+ iks_md5_hash (md5, (const unsigned char*)realm, iks_strlen (realm), 0);
+ iks_md5_hash (md5, (const unsigned char*)":", 1, 0);
+ iks_md5_hash (md5, (const unsigned char*)data->auth_pass, iks_strlen (data->auth_pass), 1);
+ iks_md5_digest (md5, a1_h);
+
+ iks_md5_reset (md5);
+ iks_md5_hash (md5, (const unsigned char*)a1_h, 16, 0);
+ iks_md5_hash (md5, (const unsigned char*)":", 1, 0);
+ iks_md5_hash (md5, (const unsigned char*)nonce, iks_strlen (nonce), 0);
+ iks_md5_hash (md5, (const unsigned char*)":", 1, 0);
+ iks_md5_hash (md5, (const unsigned char*)cnonce, iks_strlen (cnonce), 1);
+ iks_md5_print (md5, (char*)a1);
+
+ iks_md5_reset (md5);
+ iks_md5_hash (md5, (const unsigned char*)"AUTHENTICATE:xmpp/", 18, 0);
+ iks_md5_hash (md5, (const unsigned char*)data->server, iks_strlen (data->server), 1);
+ iks_md5_print (md5, (char*)a2);
+
+ iks_md5_reset (md5);
+ iks_md5_hash (md5, (const unsigned char*)a1, 32, 0);
+ iks_md5_hash (md5, (const unsigned char*)":", 1, 0);
+ iks_md5_hash (md5, (const unsigned char*)nonce, iks_strlen (nonce), 0);
+ iks_md5_hash (md5, (const unsigned char*)":00000001:", 10, 0);
+ iks_md5_hash (md5, (const unsigned char*)cnonce, iks_strlen (cnonce), 0);
+ iks_md5_hash (md5, (const unsigned char*)":auth:", 6, 0);
+ iks_md5_hash (md5, (const unsigned char*)a2, 32, 1);
+ iks_md5_print (md5, (char*)response_value);
+
+ iks_md5_delete (md5);
+
+ i = iks_strlen (data->auth_username) + iks_strlen (realm) +
+ iks_strlen (nonce) + iks_strlen (data->server) +
+ CNONCE_LEN*8 + 136;
+ response = iks_malloc (i);
+ if (!response) return NULL;
+
+ sprintf (response, "username=\"%s\",realm=\"%s\",nonce=\"%s\""
+ ",cnonce=\"%s\",nc=00000001,qop=auth,digest-uri=\""
+ "xmpp/%s\",response=%s,charset=utf-8",
+ data->auth_username, realm, nonce, cnonce,
+ data->server, response_value);
+
+ response_coded = iks_base64_encode (response, 0);
+ if (response_coded) {
+ x = iks_new ("response");
+ iks_insert_cdata (x, response_coded, 0);
+ iks_free (response_coded);
+ }
+ iks_free (response);
+
+ return x;
+}
+
+static void
+iks_sasl_challenge (struct stream_data *data, iks *challenge)
+{
+ char *message;
+ iks *x;
+ char *tmp;
+
+ tmp = iks_cdata (iks_child (challenge));
+ if (!tmp) return;
+
+ /* decode received blob */
+ message = iks_base64_decode (tmp);
+ if (!message) return;
+
+ /* reply the challenge */
+ if (strstr (message, "rspauth")) {
+ x = iks_new ("response");
+ } else {
+ x = make_sasl_response (data, message);
+ }
+ if (x) {
+ iks_insert_attrib (x, "xmlns", IKS_NS_XMPP_SASL);
+ iks_send (data->prs, x);
+ iks_delete (x);
+ }
+ iks_free (message);
+}
+
+static int
+tagHook (struct stream_data *data, char *name, char **atts, int type)
+{
+ iks *x;
+ int err;
+
+ switch (type) {
+ case IKS_OPEN:
+ case IKS_SINGLE:
+#ifdef HAVE_GNUTLS
+ if (data->flags & SF_TRY_SECURE) {
+ if (strcmp (name, "proceed") == 0) {
+ err = handshake (data);
+ return err;
+ } else if (strcmp (name, "failure") == 0){
+ return IKS_NET_TLSFAIL;
+ }
+ }
+#endif
+ if (data->current) {
+ x = iks_insert (data->current, name);
+ insert_attribs (x, atts);
+ } else {
+ x = iks_new (name);
+ insert_attribs (x, atts);
+ if (iks_strcmp (name, "stream:stream") == 0) {
+ err = data->streamHook (data->user_data, IKS_NODE_START, x);
+ if (err != IKS_OK) return err;
+ break;
+ }
+ }
+ data->current = x;
+ if (IKS_OPEN == type) break;
+ case IKS_CLOSE:
+ x = data->current;
+ if (NULL == x) {
+ err = data->streamHook (data->user_data, IKS_NODE_STOP, NULL);
+ if (err != IKS_OK) return err;
+ break;
+ }
+ if (NULL == iks_parent (x)) {
+ data->current = NULL;
+ if (iks_strcmp (name, "challenge") == 0)
+ iks_sasl_challenge(data, x);
+ else if (iks_strcmp (name, "stream:error") == 0) {
+ err = data->streamHook (data->user_data, IKS_NODE_ERROR, x);
+ if (err != IKS_OK) return err;
+ } else {
+ err = data->streamHook (data->user_data, IKS_NODE_NORMAL, x);
+ if (err != IKS_OK) return err;
+ }
+ break;
+ }
+ data->current = iks_parent (x);
+ }
+ return IKS_OK;
+}
+
+static int
+cdataHook (struct stream_data *data, char *cdata, size_t len)
+{
+ if (data->current) iks_insert_cdata (data->current, cdata, len);
+ return IKS_OK;
+}
+
+static void
+deleteHook (struct stream_data *data)
+{
+#ifdef HAVE_GNUTLS
+ if (data->flags & SF_SECURE) {
+ gnutls_bye (data->sess, GNUTLS_SHUT_WR);
+ gnutls_deinit (data->sess);
+ gnutls_certificate_free_credentials (data->cred);
+ }
+#endif
+ if (data->trans) data->trans->close (data->sock);
+ data->trans = NULL;
+ if (data->current) iks_delete (data->current);
+ data->current = NULL;
+ data->flags = 0;
+}
+
+iksparser *
+iks_stream_new (char *name_space, void *user_data, iksStreamHook *streamHook)
+{
+ ikstack *s;
+ struct stream_data *data;
+
+ s = iks_stack_new (DEFAULT_STREAM_CHUNK_SIZE, 0);
+ if (NULL == s) return NULL;
+ data = iks_stack_alloc (s, sizeof (struct stream_data));
+ memset (data, 0, sizeof (struct stream_data));
+ data->s = s;
+ data->prs = iks_sax_extend (s, data, (iksTagHook *)tagHook, (iksCDataHook *)cdataHook, (iksDeleteHook *)deleteHook);
+ data->name_space = name_space;
+ data->user_data = user_data;
+ data->streamHook = streamHook;
+ return data->prs;
+}
+
+void *
+iks_stream_user_data (iksparser *prs)
+{
+ struct stream_data *data = iks_user_data (prs);
+
+ return data->user_data;
+}
+
+void
+iks_set_log_hook (iksparser *prs, iksLogHook *logHook)
+{
+ struct stream_data *data = iks_user_data (prs);
+
+ data->logHook = logHook;
+}
+
+int
+iks_connect_tcp (iksparser *prs, const char *server, int port)
+{
+#ifdef USE_DEFAULT_IO
+ return iks_connect_with (prs, server, port, server, &iks_default_transport);
+#else
+ return IKS_NET_NOTSUPP;
+#endif
+}
+
+int
+iks_connect_via (iksparser *prs, const char *server, int port, const char *server_name)
+{
+#ifdef USE_DEFAULT_IO
+ return iks_connect_with (prs, server, port, server_name, &iks_default_transport);
+#else
+ return IKS_NET_NOTSUPP;
+#endif
+}
+
+int
+iks_connect_with (iksparser *prs, const char *server, int port, const char *server_name, ikstransport *trans)
+{
+ struct stream_data *data = iks_user_data (prs);
+ int ret;
+
+ if (!trans->connect) return IKS_NET_NOTSUPP;
+
+ if (!data->buf) {
+ data->buf = iks_stack_alloc (data->s, NET_IO_BUF_SIZE);
+ if (NULL == data->buf) return IKS_NOMEM;
+ }
+
+ ret = trans->connect (prs, &data->sock, server, port);
+ if (ret) return ret;
+
+ data->trans = trans;
+
+ return iks_send_header (prs, server_name);
+}
+
+int
+iks_connect_async (iksparser *prs, const char *server, int port, void *notify_data, iksAsyncNotify *notify_func)
+{
+#ifdef USE_DEFAULT_IO
+ return iks_connect_async_with (prs, server, port, server, &iks_default_transport, notify_data, notify_func);
+#else
+ return IKS_NET_NOTSUPP;
+#endif
+}
+
+int
+iks_connect_async_with (iksparser *prs, const char *server, int port, const char *server_name, ikstransport *trans, void *notify_data, iksAsyncNotify *notify_func)
+{
+ struct stream_data *data = iks_user_data (prs);
+ int ret;
+
+ if (NULL == trans->connect_async)
+ return IKS_NET_NOTSUPP;
+
+ if (!data->buf) {
+ data->buf = iks_stack_alloc (data->s, NET_IO_BUF_SIZE);
+ if (NULL == data->buf) return IKS_NOMEM;
+ }
+
+ ret = trans->connect_async (prs, &data->sock, server, server_name, port, notify_data, notify_func);
+ if (ret) return ret;
+
+ data->trans = trans;
+ data->server = server_name;
+
+ return IKS_OK;
+}
+
+int
+iks_connect_fd (iksparser *prs, int fd)
+{
+#ifdef USE_DEFAULT_IO
+ struct stream_data *data = iks_user_data (prs);
+
+ if (!data->buf) {
+ data->buf = iks_stack_alloc (data->s, NET_IO_BUF_SIZE);
+ if (NULL == data->buf) return IKS_NOMEM;
+ }
+
+ data->sock = (void *) fd;
+ data->flags |= SF_FOREIGN;
+ data->trans = &iks_default_transport;
+
+ return IKS_OK;
+#else
+ return IKS_NET_NOTSUPP;
+#endif
+}
+
+int
+iks_fd (iksparser *prs)
+{
+ struct stream_data *data = iks_user_data (prs);
+
+ return (int) data->sock;
+}
+
+int
+iks_recv (iksparser *prs, int timeout)
+{
+ struct stream_data *data = iks_user_data (prs);
+ int len, ret;
+
+ while (1) {
+#ifdef HAVE_GNUTLS
+ if (data->flags & SF_SECURE) {
+ len = gnutls_record_recv (data->sess, data->buf, NET_IO_BUF_SIZE - 1);
+ } else
+#endif
+ {
+ len = data->trans->recv (data->sock, data->buf, NET_IO_BUF_SIZE - 1, timeout);
+ }
+ if (len < 0) return IKS_NET_RWERR;
+ if (len == 0) break;
+ data->buf[len] = '\0';
+ if (data->logHook) data->logHook (data->user_data, data->buf, len, 1);
+ ret = iks_parse (prs, data->buf, len, 0);
+ if (ret != IKS_OK) return ret;
+ if (!data->trans) {
+ /* stream hook called iks_disconnect */
+ return IKS_NET_NOCONN;
+ }
+ timeout = 0;
+ }
+ return IKS_OK;
+}
+
+int
+iks_send_header (iksparser *prs, const char *to)
+{
+ struct stream_data *data = iks_user_data (prs);
+ char *msg;
+ int len, err;
+
+ len = 91 + strlen (data->name_space) + 6 + strlen (to) + 16 + 1;
+ msg = iks_malloc (len);
+ if (!msg) return IKS_NOMEM;
+ sprintf (msg, "<?xml version='1.0'?>"
+ "<stream:stream xmlns:stream='http://etherx.jabber.org/streams' xmlns='"
+ "%s' to='%s' version='1.0'>", data->name_space, to);
+ err = iks_send_raw (prs, msg);
+ iks_free (msg);
+ if (err) return err;
+ data->server = to;
+ return IKS_OK;
+}
+
+int
+iks_send (iksparser *prs, iks *x)
+{
+ return iks_send_raw (prs, iks_string (iks_stack (x), x));
+}
+
+int
+iks_send_raw (iksparser *prs, const char *xmlstr)
+{
+ struct stream_data *data = iks_user_data (prs);
+ int ret;
+
+#ifdef HAVE_GNUTLS
+ if (data->flags & SF_SECURE) {
+ if (gnutls_record_send (data->sess, xmlstr, strlen (xmlstr)) < 0) return IKS_NET_RWERR;
+ } else
+#endif
+ {
+ ret = data->trans->send (data->sock, xmlstr, strlen (xmlstr));
+ if (ret) return ret;
+ }
+ if (data->logHook) data->logHook (data->user_data, xmlstr, strlen (xmlstr), 0);
+ return IKS_OK;
+}
+
+void
+iks_disconnect (iksparser *prs)
+{
+ iks_parser_reset (prs);
+}
+
+/***** tls api *****/
+
+int
+iks_has_tls (void)
+{
+#ifdef HAVE_GNUTLS
+ return 1;
+#else
+ return 0;
+#endif
+}
+
+int
+iks_is_secure (iksparser *prs)
+{
+#ifdef HAVE_GNUTLS
+ struct stream_data *data = iks_user_data (prs);
+
+ return data->flags & SF_SECURE;
+#else
+ return 0;
+#endif
+}
+
+int
+iks_start_tls (iksparser *prs)
+{
+#ifdef HAVE_GNUTLS
+ int ret;
+ struct stream_data *data = iks_user_data (prs);
+
+ ret = iks_send_raw (prs, "<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>");
+ if (ret) return ret;
+ data->flags |= SF_TRY_SECURE;
+ return IKS_OK;
+#else
+ return IKS_NET_NOTSUPP;
+#endif
+}
+
+/***** sasl *****/
+
+int
+iks_start_sasl (iksparser *prs, enum ikssasltype type, char *username, char *pass)
+{
+ iks *x;
+
+ x = iks_new ("auth");
+ iks_insert_attrib (x, "xmlns", IKS_NS_XMPP_SASL);
+ switch (type) {
+ case IKS_SASL_PLAIN: {
+ int len = iks_strlen (username) + iks_strlen (pass) + 2;
+ char *s = iks_malloc (80+len);
+ char *base64;
+
+ iks_insert_attrib (x, "mechanism", "PLAIN");
+ sprintf (s, "%c%s%c%s", 0, username, 0, pass);
+ base64 = iks_base64_encode (s, len);
+ iks_insert_cdata (x, base64, 0);
+ iks_free (base64);
+ iks_free (s);
+ break;
+ }
+ case IKS_SASL_DIGEST_MD5: {
+ struct stream_data *data = iks_user_data (prs);
+
+ iks_insert_attrib (x, "mechanism", "DIGEST-MD5");
+ data->auth_username = username;
+ data->auth_pass = pass;
+ break;
+ }
+ default:
+ iks_delete (x);
+ return IKS_NET_NOTSUPP;
+ }
+ iks_send (prs, x);
+ iks_delete (x);
+ return IKS_OK;
+}
diff --git a/src/utility.c b/src/utility.c
new file mode 100644
index 0000000..1586b32
--- /dev/null
+++ b/src/utility.c
@@ -0,0 +1,180 @@
+/* iksemel (XML parser for Jabber)
+** Copyright (C) 2000-2003 Gurer Ozen <madcat@e-kolay.net>
+** This code is free software; you can redistribute it and/or
+** modify it under the terms of GNU Lesser General Public License.
+*/
+
+#include "common.h"
+#include "iksemel.h"
+
+/***** malloc wrapper *****/
+
+static void *(*my_malloc_func)(size_t size);
+static void (*my_free_func)(void *ptr);
+
+void *
+iks_malloc (size_t size)
+{
+ if (my_malloc_func)
+ return my_malloc_func (size);
+ else
+ return malloc (size);
+}
+
+void
+iks_free (void *ptr)
+{
+ if (my_free_func)
+ my_free_func (ptr);
+ else
+ free (ptr);
+}
+
+void
+iks_set_mem_funcs (void *(*malloc_func)(size_t size), void (*free_func)(void *ptr))
+{
+ my_malloc_func = malloc_func;
+ my_free_func = free_func;
+}
+
+/***** NULL-safe Functions *****/
+
+char *
+iks_strdup (const char *src)
+{
+ if (src) return strdup(src);
+ return NULL;
+}
+
+char *
+iks_strcat (char *dest, const char *src)
+{
+ size_t len;
+
+ if (!src) return dest;
+
+ len = strlen (src);
+ memcpy (dest, src, len);
+ dest[len] = '\0';
+ return dest + len;
+}
+
+int
+iks_strcmp (const char *a, const char *b)
+{
+ if (!a || !b) return -1;
+ return strcmp (a, b);
+}
+
+int
+iks_strcasecmp (const char *a, const char *b)
+{
+ if (!a || !b) return -1;
+ return strcasecmp (a, b);
+}
+
+int
+iks_strncmp (const char *a, const char *b, size_t n)
+{
+ if (!a || !b) return -1;
+ return strncmp (a, b, n);
+}
+
+int
+iks_strncasecmp (const char *a, const char *b, size_t n)
+{
+ if (!a || !b) return -1;
+ return strncasecmp (a, b, n);
+}
+
+size_t
+iks_strlen (const char *src)
+{
+ if (!src) return 0;
+ return strlen (src);
+}
+
+/***** XML Escaping *****/
+
+char *
+iks_escape (ikstack *s, char *src, size_t len)
+{
+ char *ret;
+ int i, j, nlen;
+
+ if (!src || !s) return NULL;
+ if (len == -1) len = strlen (src);
+
+ nlen = len;
+ for (i=0; i<len; i++) {
+ switch (src[i]) {
+ case '&': nlen += 4; break;
+ case '<': nlen += 3; break;
+ case '>': nlen += 3; break;
+ case '\'': nlen += 5; break;
+ case '"': nlen += 5; break;
+ }
+ }
+ if (len == nlen) return src;
+
+ ret = iks_stack_alloc (s, nlen + 1);
+ if (!ret) return NULL;
+
+ for (i=j=0; i<len; i++) {
+ switch (src[i]) {
+ case '&': memcpy (&ret[j], "&amp;", 5); j += 5; break;
+ case '\'': memcpy (&ret[j], "&apos;", 6); j += 6; break;
+ case '"': memcpy (&ret[j], "&quot;", 6); j += 6; break;
+ case '<': memcpy (&ret[j], "&lt;", 4); j += 4; break;
+ case '>': memcpy (&ret[j], "&gt;", 4); j += 4; break;
+ default: ret[j++] = src[i];
+ }
+ }
+ ret[j] = '\0';
+
+ return ret;
+}
+
+char *
+iks_unescape (ikstack *s, char *src, size_t len)
+{
+ int i,j;
+ char *ret;
+
+ if (!s || !src) return NULL;
+ if (!strchr (src, '&')) return src;
+ if (len == -1) len = strlen (src);
+
+ ret = iks_stack_alloc (s, len + 1);
+ if (!ret) return NULL;
+
+ for (i=j=0; i<len; i++) {
+ if (src[i] == '&') {
+ i++;
+ if (strncmp (&src[i], "amp;", 4) == 0) {
+ ret[j] = '&';
+ i += 3;
+ } else if (strncmp (&src[i], "quot;", 5) == 0) {
+ ret[j] = '"';
+ i += 4;
+ } else if (strncmp (&src[i], "apos;", 5) == 0) {
+ ret[j] = '\'';
+ i += 4;
+ } else if (strncmp (&src[i], "lt;", 3) == 0) {
+ ret[j] = '<';
+ i += 2;
+ } else if (strncmp (&src[i], "gt;", 3) == 0) {
+ ret[j] = '>';
+ i += 2;
+ } else {
+ ret[j] = src[--i];
+ }
+ } else {
+ ret[j] = src[i];
+ }
+ j++;
+ }
+ ret[j] = '\0';
+
+ return ret;
+}