From 6428c4c42b26ee55360626ec9c0574cb3d71abf8 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Zden=C4=9Bk=20=C5=A0ustr?= Date: Fri, 6 Aug 2010 14:38:25 +0000 Subject: [PATCH] Module relocated from org.glite.security --- org.glite.lbjp-common.gsoap-plugin/LICENSE | 69 + org.glite.lbjp-common.gsoap-plugin/Makefile | 297 + org.glite.lbjp-common.gsoap-plugin/build.xml | 128 + org.glite.lbjp-common.gsoap-plugin/configure | 927 ++ .../examples/calc.h.S | 13 + .../examples/wscalc_clt_ex.c | 69 + .../examples/wscalc_srv_ex.c | 128 + .../examples/wscalc_srv_ex2.c | 167 + .../interface/glite_gscompat.h | 111 + .../interface/glite_gsplugin-int.h | 45 + .../interface/glite_gsplugin.h | 51 + .../project/ChangeLog | 45 + .../project/build.number | 1 + .../project/build.properties | 0 .../project/configure.properties.xml | 54 + .../project/libtoolhack/gcc | 1 + .../project/package.description | 1 + .../project/package.summary | 1 + .../project/properties.xml | 55 + .../project/tar_exclude | 10 + .../project/version.properties | 3 + .../src/glite_gsplugin.c | 594 + .../src/stdsoap2_2.6.2.c | 11020 ++++++++++++++ .../src/stdsoap2_2.6.2.h | 1647 ++ .../src/stdsoap2_2.7.0.c | 11692 +++++++++++++++ .../src/stdsoap2_2.7.0.h | 1764 +++ .../src/stdsoap2_2.7.0f.c | 12026 +++++++++++++++ .../src/stdsoap2_2.7.0f.h | 1885 +++ .../src/stdsoap2_2.7.10.c | 14890 +++++++++++++++++++ .../src/stdsoap2_2.7.10.h | 2281 +++ .../src/stdsoap2_2.7.6b.c | 13101 ++++++++++++++++ .../src/stdsoap2_2.7.6b.h | 2053 +++ .../src/stdsoap2_2.7.6d.c | 13362 +++++++++++++++++ .../src/stdsoap2_2.7.6d.h | 2075 +++ .../src/stdsoap2_2.7.9b.c | 14172 ++++++++++++++++++ .../src/stdsoap2_2.7.9b.h | 2166 +++ .../src/stdsoap2_2.7.9d.c | 14414 ++++++++++++++++++ .../src/stdsoap2_2.7.9d.h | 2184 +++ .../src/stdsoap2_2.7.9l.c | 14748 ++++++++++++++++++ .../src/stdsoap2_2.7.9l.h | 2229 +++ .../test/test_gsplugin_cxx.cpp | 63 + org.glite.lbjp-common.gss/LICENSE | 69 + org.glite.lbjp-common.gss/Makefile | 153 + org.glite.lbjp-common.gss/configure | 927 ++ org.glite.lbjp-common.gss/interface/glite_gss.h | 185 + org.glite.lbjp-common.gss/project/ChangeLog | 39 + .../project/package.description | 1 + org.glite.lbjp-common.gss/project/package.summary | 1 + .../project/version.properties | 3 + org.glite.lbjp-common.gss/src/glite_gss.c | 1536 ++ org.glite.lbjp-common.gss/test/test_gss.cpp | 237 + 51 files changed, 143693 insertions(+) create mode 100644 org.glite.lbjp-common.gsoap-plugin/LICENSE create mode 100644 org.glite.lbjp-common.gsoap-plugin/Makefile create mode 100755 org.glite.lbjp-common.gsoap-plugin/build.xml create mode 100755 org.glite.lbjp-common.gsoap-plugin/configure create mode 100644 org.glite.lbjp-common.gsoap-plugin/examples/calc.h.S create mode 100644 org.glite.lbjp-common.gsoap-plugin/examples/wscalc_clt_ex.c create mode 100644 org.glite.lbjp-common.gsoap-plugin/examples/wscalc_srv_ex.c create mode 100644 org.glite.lbjp-common.gsoap-plugin/examples/wscalc_srv_ex2.c create mode 100644 org.glite.lbjp-common.gsoap-plugin/interface/glite_gscompat.h create mode 100644 org.glite.lbjp-common.gsoap-plugin/interface/glite_gsplugin-int.h create mode 100644 org.glite.lbjp-common.gsoap-plugin/interface/glite_gsplugin.h create mode 100644 org.glite.lbjp-common.gsoap-plugin/project/ChangeLog create mode 100644 org.glite.lbjp-common.gsoap-plugin/project/build.number create mode 100644 org.glite.lbjp-common.gsoap-plugin/project/build.properties create mode 100644 org.glite.lbjp-common.gsoap-plugin/project/configure.properties.xml create mode 100755 org.glite.lbjp-common.gsoap-plugin/project/libtoolhack/gcc create mode 100644 org.glite.lbjp-common.gsoap-plugin/project/package.description create mode 100644 org.glite.lbjp-common.gsoap-plugin/project/package.summary create mode 100755 org.glite.lbjp-common.gsoap-plugin/project/properties.xml create mode 100644 org.glite.lbjp-common.gsoap-plugin/project/tar_exclude create mode 100644 org.glite.lbjp-common.gsoap-plugin/project/version.properties create mode 100644 org.glite.lbjp-common.gsoap-plugin/src/glite_gsplugin.c create mode 100644 org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.6.2.c create mode 100644 org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.6.2.h create mode 100644 org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.0.c create mode 100644 org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.0.h create mode 100644 org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.0f.c create mode 100644 org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.0f.h create mode 100644 org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.10.c create mode 100644 org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.10.h create mode 100644 org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.6b.c create mode 100644 org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.6b.h create mode 100644 org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.6d.c create mode 100644 org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.6d.h create mode 100644 org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.9b.c create mode 100644 org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.9b.h create mode 100644 org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.9d.c create mode 100644 org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.9d.h create mode 100644 org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.9l.c create mode 100644 org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.9l.h create mode 100644 org.glite.lbjp-common.gsoap-plugin/test/test_gsplugin_cxx.cpp create mode 100644 org.glite.lbjp-common.gss/LICENSE create mode 100644 org.glite.lbjp-common.gss/Makefile create mode 100755 org.glite.lbjp-common.gss/configure create mode 100644 org.glite.lbjp-common.gss/interface/glite_gss.h create mode 100644 org.glite.lbjp-common.gss/project/ChangeLog create mode 100644 org.glite.lbjp-common.gss/project/package.description create mode 100644 org.glite.lbjp-common.gss/project/package.summary create mode 100644 org.glite.lbjp-common.gss/project/version.properties create mode 100644 org.glite.lbjp-common.gss/src/glite_gss.c create mode 100644 org.glite.lbjp-common.gss/test/test_gss.cpp diff --git a/org.glite.lbjp-common.gsoap-plugin/LICENSE b/org.glite.lbjp-common.gsoap-plugin/LICENSE new file mode 100644 index 0000000..259a91f --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/LICENSE @@ -0,0 +1,69 @@ +LICENSE file for EGEE Middleware +================================ + +Copyright (c) 2004 on behalf of the EU EGEE Project: +The European Organization for Nuclear Research (CERN), +Istituto Nazionale di Fisica Nucleare (INFN), Italy +Datamat Spa, Italy +Centre National de la Recherche Scientifique (CNRS), France +CS Systeme d'Information (CSSI), France +Royal Institute of Technology, Center for Parallel Computers (KTH-PDC), Sweden +Universiteit van Amsterdam (UvA), Netherlands +University of Helsinki (UH.HIP), Finlan +University of Bergen (UiB), Norway +Council for the Central Laboratory of the Research Councils (CCLRC), United Kingdom + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +3. The end-user documentation included with the redistribution, if +any, must include the following acknowledgment: "This product includes +software developed by The EU EGEE Project (http://cern.ch/eu-egee/)." +Alternatively, this acknowledgment may appear in the software itself, if +and wherever such third-party acknowledgments normally appear. + +4. The names EGEE and the EU EGEE Project must not be +used to endorse or promote products derived from this software without +prior written permission. For written permission, please contact +. + +5. You are under no obligation whatsoever to provide anyone with any +bug fixes, patches, or upgrades to the features, functionality or +performance of the Software ("Enhancements") that you may develop over +time; however, if you choose to provide your Enhancements to The EU +EGEE Project, or if you choose to otherwise publish or distribute your +Enhancements, in source code form without contemporaneously requiring +end users of The EU EGEE Proejct to enter into a separate written license +agreement for such Enhancements, then you hereby grant The EU EGEE Project +a non-exclusive, royalty-free perpetual license to install, use, copy, +modify, prepare derivative works, incorporate into the EGEE Middleware +or any other computer software, distribute, and sublicense your +Enhancements or derivative works thereof, in binary and source code +form (if any), whether developed by The EU EGEE Project or third parties. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL PROJECT OR ITS CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +This software consists of voluntary contributions made by many +individuals on behalf of the EU EGEE Prject. For more information on The +EU EGEE Project, please see http://cern.ch/eu-egee/. For more information on +EGEE Middleware, please see http://egee-jra1.web.cern.ch/egee-jra1/ + + diff --git a/org.glite.lbjp-common.gsoap-plugin/Makefile b/org.glite.lbjp-common.gsoap-plugin/Makefile new file mode 100644 index 0000000..6b1976d --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/Makefile @@ -0,0 +1,297 @@ +# defaults +top_srcdir=.. +builddir=build +top_builddir=${top_srcdir}/${builddir} +stagedir=. +globalprefix=glite +package=gsoap-plugin +version=1.0.0 +PREFIX=/opt/glite + +glite_location=/opt/glite +nothrflavour=gcc32 +thrflavour=gcc32pthr +gsoap_prefix=/opt/gsoap + +CC=gcc + +gsoap_versions_noflavours?=2.6.2 2.7.0f 2.7.6b 2.7.6d 2.7.9d 2.7.9b +gsoap_versions_flavours?=2.7.10 2.7.9l +gsoap_versions_flavours:=${shell if ! echo $gsoap_versions_flavours | grep "\<${gsoap_default_version}\>" >/dev/null; then echo "${gsoap_default_version} "; else echo ne; fi} ${gsoap_versions_flavours} + +-include Makefile.inc +-include ../Makefile.inc +-include ../project/version.properties +-include ../../project/version.properties + +version=${module.version} + +GSPLUGIN_DEBUG?=no +GSPLUGIN_VERSION_CHECKING?=yes +CC=gcc + +# In order to use libtool versioning correcty, we must have: +# +# current = major + minor + offset +# revision = patch +# age = minor +# +# where offset is a sum of maximal released minor's of all previous major's +# + +# counted minors: 1.5 +# TODO: bump offset to 5 on next major change +offset=-1 +version_info:=-version-info ${shell \ + perl -e '$$,=":"; @F=split "\\.","${version}"; print $$F[0]+$$F[1]+${offset},$$F[2],$$F[1]' } + +ext_repository:=${shell if [ -d "${repository}/externals" ]; then \ + echo "${repository}/externals"; \ + else echo "${repository}"; \ + fi} + +gsoap_version=${gsoap_default_version} +gsoap_prefix?=${ext_repository}/${gsoap_name}/${gsoap_version}/${gsoap_platform} +ifdef lang +langflavour:=_${lang} +langsuffix:=.${lang} +endif + +VPATH=${top_srcdir}/src:${top_srcdir}/test:${top_srcdir}/examples + +default: all + +DEBUG:=-g -O0 -W -Wall -Wno-unused-parameter +# not for globus and gsoap: -Werror +ifeq ($(GSPLUGIN_DEBUG),yes) + DEBUG:=${DEBUG} -DGSPLUGIN_DEBUG=1 +endif +# gsoap logs: -DDEBUG +ifeq ($(GSOAP_DEBUG),yes) + DEBUG:=${DEBUG} -DDEBUG=1 +endif + +#ifeq ($(GSPLUGIN_VERSION_CHECKING),yes) +# DEBUG:=${DEBUG} -DCHECK_GSOAP_VERSION +#endif + +CFLAGS:= ${DEBUG} \ + -DVERSION=\"${version}\" \ + -DWITH_NONAMESPACES \ + -I. -I${top_srcdir}/interface \ + -I${stagedir}/include \ + ${COVERAGE_FLAGS} -D_GNU_SOURCE -DDATAGRID_EXTENSION -DWITH_IPV6 + +LDFLAGS:=${COVERAGE_FLAGS} + +COMPILE:=libtool --mode=compile ${CC} ${CFLAGS} +COMPILEXX:=libtool --mode=compile ${CXX} ${CFLAGS} +LINK:=libtool --mode=link ${CC} -rpath ${stagedir}/${libdir} ${LDFLAGS} +LINKXX:=libtool --mode=link ${CXX} -rpath ${stagedir}/${libdir} ${LDFLAGS} +INSTALL:=libtool --mode=install install +LINK_lang:=PATH=${top_srcdir}/project/libtoolhack:${PATH} libtool --mode=link ${CXX} -rpath ${stagedir}/${libdir} ${LDFLAGS} +ifeq (${lang},c) +LINK_lang:=${LINK} +endif +ifeq (${lang},cxx) +LINK_lang:=${LINKXX} +endif + +EX_LIBS:=-L${stagedir}/${libdir} -lglite_security_gss_${nothrflavour} +EX_THRLIBS:=-L${stagedir}/${libdir} -lglite_security_gss_${thrflavour} +HDRS:=glite_gsplugin.h glite_gscompat.h glite_gsplugin-int.h +EXAMPLES:=wscalc_clt_ex wscalc_srv_ex wscalc_srv_ex2 +TESTS:=test_cxx + +STATICLIB:=libglite_security_gsoap_plugin_${nothrflavour}${langflavour}.a +THRSTATICLIB:=libglite_security_gsoap_plugin_${thrflavour}${langflavour}.a +LTLIB:=libglite_security_gsoap_plugin_${nothrflavour}${langflavour}.la +THRLTLIB:=libglite_security_gsoap_plugin_${thrflavour}${langflavour}.la + +OBJS:=${GSS_OBJS} glite_gsplugin${langsuffix}.o +LOBJS:=${OBJS:.o=.lo} +THROBJS:=${OBJS:.o=.thr.o} +THRLOBJS:=${OBJS:.o=.thr.lo} + +dotless_ver:=${shell echo ${gsoap_version} | tr -d '.'} +STATICLIB_S:=libglite_security_gsoap_plugin_${dotless_ver}_${nothrflavour}${langflavour}.a +THRSTATICLIB_S:=libglite_security_gsoap_plugin_${dotless_ver}_${thrflavour}${langflavour}.a +LTLIB_S:=libglite_security_gsoap_plugin_${dotless_ver}_${nothrflavour}${langflavour}.la +THRLTLIB_S:=libglite_security_gsoap_plugin_${dotless_ver}_${thrflavour}${langflavour}.la +LTLIB_TEST_S:=libglite_security_gsoap_plugin_${dotless_ver}_${nothrflavour}_cxx.la + +OBJS_S:=glite_gsplugin${langsuffix}.o stdsoap2${langsuffix}.o +LOBJS_S:=${OBJS_S:.o=.lo} +THROBJS_S:=${OBJS_S:.o=.thr.o} +THRLOBJS_S:=${OBJS_S:.o=.thr.lo} + +${STATICLIB}: ${OBJS} + ar crv $@ ${OBJS} + ranlib $@ + +${THRSTATICLIB}: ${THROBJS} + ar crv $@ ${THROBJS} + ranlib $@ + +${LTLIB}: ${OBJS} + ${LINK_lang} ${version_info} -o $@ ${LOBJS} ${EX_LIBS} + +${THRLTLIB}: ${THROBJS} + ${LINK_lang} ${version_info} -o $@ ${THRLOBJS} ${EX_THRLIBS} + +${STATICLIB_S}: ${OBJS_S} + ar crv $@ ${OBJS_S} + ranlib $@ + +${THRSTATICLIB_S}: ${THROBJS_S} + ar crv $@ ${THROBJS_S} + ranlib $@ + +${LTLIB_S}: ${OBJS_S} + ${LINK_lang} ${version_info} -o $@ ${LOBJS_S} ${EX_LIBS} + +${THRLTLIB_S}: ${THROBJS_S} + ${LINK_lang} ${version_info} -o $@ ${THRLOBJS_S} ${EX_THRLIBS} + +all compile: \ + ${STATICLIB} ${LTLIB} ${THRSTATICLIB} ${THRLTLIB} \ + all-libs-with-soap examples + +check: check.cxx + +# C/C++ compatibility test +# (C flavour, gsoap 2.7.10 ==> C++ test fails) +check.cxx: + ${MAKE} lang=cxx -f ${top_srcdir}/Makefile ${LTLIB_TEST_S} test_cxx + LD_LIBRARY_PATH=${cares_prefix}/${libdir}:${LD_LIBRARY_PATH} ./test_cxx + +examples: ${EXAMPLES} + +all-libs-with-soap: + for v in ${gsoap_versions_noflavours}; do \ + dir=`echo $$v | tr -d .`; \ + mkdir $$dir; \ + ${MAKE} -C $$dir -f ../Makefile gsoap_version=$$v top_srcdir=../.. lang= libs-with-soap || exit $?; \ + done + for v in ${gsoap_versions_flavours}; do \ + dir=`echo $$v | tr -d .`; \ + mkdir $$dir; \ + ${MAKE} -C $$dir -f ../Makefile gsoap_version=$$v top_srcdir=../.. lang=c libs-with-soap || exit $?; \ + ${MAKE} -C $$dir -f ../Makefile gsoap_version=$$v top_srcdir=../.. lang=cxx libs-with-soap || exit $?; \ + done + +libs-with-soap: ${LTLIB_S} ${THRLTLIB_S} ${STATICLIB_S} ${THRSTATICLIB_S} + +gsoap_srcname=gsoap-`echo ${gsoap_version} | cut -d. -f1,2` + +link-gsoap: + if [ -f ${top_srcdir}/src/stdsoap2_${gsoap_version}.c ]; then \ + ln -sf ${top_srcdir}/src/stdsoap2_${gsoap_version}.c stdsoap2.c; \ + ln -sf ${top_srcdir}/src/stdsoap2_${gsoap_version}.h stdsoap2.h; \ + elif [ -f ${ext_repository}/${gsoap_name}/${gsoap_version}/src/stdsoap2.c ]; then \ + ln -sf ${ext_repository}/${gsoap_name}/${gsoap_version}/src/stdsoap2.[ch] .; \ + elif [ -f ${ext_repository}/${gsoap_name}/${gsoap_version}/${gsoap_platform}/stdsoap2.c ]; then \ + ln -sf ${ext_repository}/${gsoap_name}/${gsoap_version}/${gsoap_platform}/stdsoap2.[ch] .; \ + elif [ -f ${ext_repository}/${gsoap_name}/${gsoap_version}/${gsoap_platform}/src/stdsoap2.c ]; then \ + ln -sf ${ext_repository}/${gsoap_name}/${gsoap_version}/${gsoap_platform}/src/stdsoap2.c .; \ + ln -sf ${ext_repository}/${gsoap_name}/${gsoap_version}/${gsoap_platform}/include/stdsoap2.h .; \ + elif [ -f ${ext_repository}/${gsoap_name}/${gsoap_version}/src/stdsoap2.c ]; then \ + ln -sf ${ext_repository}/${gsoap_name}/${gsoap_version}/src/stdsoap2.[ch] .; \ + elif [ -f ${ext_repository}/${gsoap_name}/${gsoap_version}/src/${gsoap_srcname}/soapcpp2/stdsoap2.c ]; then \ + ln -sf ${ext_repository}/${gsoap_name}/${gsoap_version}/src/${gsoap_srcname}/soapcpp2/stdsoap2.[ch] .; \ + else false ; \ + fi + +stdsoap2.c stdsoap2.h: link-gsoap + +GSOAP_FPREFIX:= GSOAP_ + +WSCALC_CLT_OBJS = wscalc_clt_ex.o ${GSOAP_FPREFIX}C.o ${GSOAP_FPREFIX}Client.o +WSCALC_SRV_OBJS = wscalc_srv_ex.o ${GSOAP_FPREFIX}C.o ${GSOAP_FPREFIX}Server.o +WSCALC_SRV2_OBJS = wscalc_srv_ex2.o ${GSOAP_FPREFIX}C.o ${GSOAP_FPREFIX}Server.o + +wscalc_clt_ex.o wscalc_srv_ex.o wscalc_srv_ex2.o: ${GSOAP_FPREFIX}H.h + +wscalc_clt_ex: ${WSCALC_CLT_OBJS} ${LTLIB_S} + ${LINK_lang} -o $@ ${WSCALC_CLT_OBJS} ${LTLIB_S} + +wscalc_srv_ex: ${WSCALC_SRV_OBJS} ${LTLIB_S} + ${LINK_lang} -o $@ ${WSCALC_SRV_OBJS} ${LTLIB_S} + +wscalc_srv_ex2: ${WSCALC_SRV2_OBJS} ${LTLIB_S} + ${LINK_lang} -o $@ ${WSCALC_SRV2_OBJS} ${LTLIB_S} + +test_cxx: test_gsplugin_cxx.o ${GSOAP_FPREFIX}C.cxx.o + ${LINKXX} -o $@ $+ ${LTLIB_TEST_S} + +soapcpp:=${shell if [ -x ${gsoap_prefix}/bin/soapcpp2 ]; then \ + echo ${gsoap_prefix}/bin/soapcpp2; \ + else echo ${gsoap_prefix}/soapcpp2; \ + fi} + +${GSOAP_FPREFIX}H.h ${GSOAP_FPREFIX}C.c ${GSOAP_FPREFIX}Server.c ${GSOAP_FPREFIX}Client.c ${GSOAP_FPREFIX}ServerLib.c ${GSOAP_FPREFIX}ClientLib.c: calc.h.S + ${soapcpp} -c -p ${GSOAP_FPREFIX} ${top_srcdir}/examples/calc.h.S + +wscalc_clt_ex.o: wscalc_clt_ex.c + ${CC} -c ${CFLAGS} -o $@ $< + +doc: + +stage: + $(MAKE) install PREFIX=${stagedir} DOSTAGE=yes + +install: + -mkdir -p ${PREFIX}/${libdir} + -mkdir -p ${PREFIX}/include/glite/security + -mkdir -p ${PREFIX}/share/doc/${package}-${version} + -mkdir -p ${PREFIX}/include/glite/security/ + ${INSTALL} -m 644 ${top_srcdir}/LICENSE ${PREFIX}/share/doc/${package}-${version} + cd ${top_srcdir}/interface && ${INSTALL} -m 644 ${HDRS} ${PREFIX}/include/glite/security/ + for v in ${gsoap_versions_noflavours}; do \ + ${MAKE} -C `echo $$v | tr -d .` -f ../Makefile install-soaplib gsoap_version=$$v lang= PREFIX=${PREFIX} top_srcdir=${top_srcdir}/.. || exit $?; \ + done + for v in ${gsoap_versions_flavours}; do \ + ${MAKE} -C `echo $$v | tr -d .` -f ../Makefile install-soaplib gsoap_version=$$v lang=c PREFIX=${PREFIX} top_srcdir=${top_srcdir}/.. || exit $?; \ + ${MAKE} -C `echo $$v | tr -d .` -f ../Makefile install-soaplib gsoap_version=$$v lang=cxx PREFIX=${PREFIX} top_srcdir=${top_srcdir}/.. || exit $?; \ + done + +install-soaplib: + ${INSTALL} -m 755 ${LTLIB_S} ${THRLTLIB_S} ${PREFIX}/${libdir} + +clean: + rm -rvf ${STATICLIB} ${LTLIB} ${THRSTATICLIB} ${THRLTLIB} + rm -rvf ${LTLIB_S} ${THRLTLIB_S} ${STATICLIB_S} ${THRSTATICLIB_S} + rm -rvf ${LTLIB_TEST_S} + rm -rvf *.c *.h *.xml *.nsmap *.o *.lo .libs ${EXAMPLES} ${TESTS} + rm -rvf CalcService.wsdl wscalc.xsd + rm -rvf log.xml project/ rpmbuild/ RPMS/ tgz/ debian/ + for v in ${gsoap_versions_noflavours} ${gsoap_versions_flavours}; do \ + rm -rvf `echo $$v | tr -d .`; \ + done + +%.c.o: %.c + ${COMPILE} -o $@ -c $< + +%.cxx.o: %.c + ${COMPILEXX} -o $@ -c $< + +%.o: %.c + ${COMPILE} -o $@ -c $< + +%.c.thr.o: %.c + ${COMPILE} -o $@ -c $< + +%.cxx.thr.o: %.c + ${COMPILEXX} -o $@ -c $< + +%.thr.o: %.c + ${COMPILE} -o $@ -c $< + +test_gsplugin_cxx.o: %.o: %.cpp stdsoap2.h + ${COMPILEXX} -c ${GLOBUS_INC} $< + +glite_gsplugin${langsuffix}.o glite_gsplugin${langsuffix}.thr.o: soap_version.h + +soap_version.h: stdsoap2.h + head stdsoap2.h | \ + perl -ne '/^\s*stdsoap2.h\s+([0-9])\.([0-9])\.(\S+)\s.*/ && printf "#define GSOAP_VERSION %d%02d%02d\n#define GSOAP_MIN_VERSION \"$$3\"\n#ident \"soap_version.h $$1.$$2.$$3\"\n",$$1,$$2,$$3' >$@ diff --git a/org.glite.lbjp-common.gsoap-plugin/build.xml b/org.glite.lbjp-common.gsoap-plugin/build.xml new file mode 100755 index 0000000..2bae60a --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/build.xml @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.glite.lbjp-common.gsoap-plugin/configure b/org.glite.lbjp-common.gsoap-plugin/configure new file mode 100755 index 0000000..d02462c --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/configure @@ -0,0 +1,927 @@ +#!/usr/bin/perl + +# WARNING: Don't edit this file unless it is the master copy in org.glite.lb +# +# For the purpose of standalone builds of lb/jobid/lbjp-common components +# it is copied on tagging + +# $Header$ +# +# Copyright (c) Members of the EGEE Collaboration. 2004-2010. +# See http://www.eu-egee.org/partners/ for details on the copyright holders. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +use Getopt::Long; + +my $pwd = `pwd`; chomp $pwd; +my $prefix = $pwd.'/stage'; +my $stagedir; +my $staged; +my $module; +my $thrflavour = 'gcc64dbgpthr'; +my $nothrflavour = 'gcc64dbg'; +my $mode = 'build'; +my $help = 0; +my $listmodules; +my $version; +my $branch; +my $output; +my $lb_tag = ''; +my $lbjp_tag = ''; +my $jp_tag = ''; +my $sec_tag = ''; +my $jobid_tag = ''; +my $libdir = getlibdir(); + +my @nodes = qw/client server logger utils client-java doc ws-test db jpprimary jpindex jpclient harvester/; +my %enable_nodes; +my %disable_nodes; + +my %extern_prefix = ( + cares => '/opt/c-ares', + classads => '/opt/classads', + cppunit => '/usr', + expat => '/usr', + globus => '/opt/globus', + gsoap => '/usr', + mysql => '/usr', + 'mysql-devel' => '', + 'mysql-server' => '', + voms => '/opt/glite', + gridsite => '/opt/glite', + lcas => '/opt/glite', + trustmanager => '/opt/glite', + utiljava => '/opt/glite', + ant => '/usr', + jdk => '/usr', + libtar => '/usr', + axis => '/usr', + log4c => '/usr', + postgresql => '/usr' +); + +my %jar = ( + 'commons-codec' => '/usr/share/java/commons-codec.jar', + 'commons-lang' => '/usr/share/java/commons-lang.jar', +); + + +my %glite_prefix; +my %need_externs; +my %need_externs_type; +my %need_jars; +my %extrafull; +my %extranodmod; +my %deps; +my %deps_type; +my %buildroot; + +my %lbmodules = ( + 'lb' => [ qw/client client-java common doc logger server state-machine types utils ws-interface ws-test harvester yaim glite-LB/], + 'security' => [qw/gss gsoap-plugin/], + 'lbjp-common' => [qw/db log maildir server-bones trio jp-interface/], + 'jobid' => [qw/api-c api-cpp api-java/], + 'jp' => [ qw/client doc index primary server-common ws-interface/ ], + 'gridsite' => [ qw/apache shared commands core/ ], + ); + + +my @opts = ( + 'prefix=s' => \$prefix, + 'staged=s' => \$staged, + 'module=s' => \$module, + 'thrflavour=s' => \$thrflavour, + 'nothrflavour=s' => \$nothrflavour, + 'mode=s' => \$mode, + 'listmodules=s' => \$listmodules, + 'version=s' => \$version, + 'branch=s' => \$branch, + 'output=s' => \$output, + 'stage=s' => \$stagedir, + 'lb-tag=s' => \$lb_tag, + 'lbjp-common-tag=s' => \$lbjp_tag, + 'jp-tag=s' => \$jp_tag, + 'security-tag=s' => \$sec_tag, + 'jobid-tag=s' => \$jobid_tag, + 'help' => \$help, + 'libdir=s' => \$libdir, +); + +for (@nodes) { + $enable_nodes{$_} = 0; + $disable_nodes{$_} = 0; + + push @opts,"disable-$_",\$disable_nodes{$_}; + push @opts,"enable-$_",\$enable_nodes{$_}; +} + +push @opts,"with-$_=s",\$extern_prefix{$_} for keys %extern_prefix; +push @opts,"with-$_=s",\$jar{$_} for keys %jar; + +my @keeparg = @ARGV; + +GetOptions @opts or die "Errors parsing command line\n"; + +$extern_prefix{'mysql-devel'}=$extern_prefix{mysql} if $extern_prefix{'mysql-devel'} eq ''; +$extern_prefix{'mysql-server'}=$extern_prefix{mysql} if $extern_prefix{'mysql-server'} eq ''; + +if ($help) { usage(); exit 0; } + +if ($listmodules) { + my @m = map "org.glite.$listmodules.$_",@{$lbmodules{$listmodules}}; + print "@m\n"; + exit 0; +} + +warn "$0: --version, --branch and --output make sense only in --mode=etics\n" + if ($version || $output || $branch) && $mode ne 'etics'; + +my $en; +for (keys %enable_nodes) { $en = 1 if $enable_nodes{$_}; } + +my $dis; +for (keys %disable_nodes) { $dis = 1 if $disable_nodes{$_}; } + +die "--enable-* and --disable-* are mutually exclusive\n" + if $en && $dis; + +die "--module cannot be used with --enable-* or --disable-*\n" + if $module && ($en || $dis); + +die "$module: unknown module\n" if $module && ! grep $module,@{$lbmodules{lb}},@{$lbmodules{security}},{$lbmodules{jp}}; + +if ($dis) { + for (@nodes) { + $enable_nodes{$_} = 1 unless $disable_nodes{$_}; + } +} + +if (!$en && !$dis) { $enable_nodes{$_} = 1 for (@nodes) } ; + +for (keys %enable_nodes) { delete $enable_nodes{$_} unless $enable_nodes{$_}; } + +$stagedir = $prefix unless $stagedir; + +if ($mode eq 'build') { + print "Writing config.status\n"; + open CONF,">config.status" or die "config.status: $!\n"; + print CONF "$0 @keeparg\n"; + close CONF; +} + + +my @modules; +my %aux; + +if ($module) { +# push @modules,split(/[,.]+/,$module); + push @modules,$module; +} +else { + @modules = map(($extranodmod{$_} ? $extranodmod{$_} : 'lb.'.$_),(keys %enable_nodes)); + + my $n; + + do { + local $"="\n"; + $n = $#modules; + push @modules,(map @{$deps{$_}},@modules); + + undef %aux; @aux{@modules} = (1) x ($#modules+1); + @modules = keys %aux; + } while ($#modules > $n); +} + +@aux{@modules} = (1) x ($#modules+1); +delete $aux{$_} for (split /,/,$staged); +@modules = keys %aux; + +mode_build() if $mode eq 'build'; +mode_checkout() if $mode eq 'checkout'; +mode_etics($module) if $mode eq 'etics'; + +sub mode_build { + print "\nBuilding modules: @modules\n"; + + my @ext = map @{$need_externs{$_}},@modules; + my @myjars = map @{$need_jars{$_}},@modules; + undef %aux; @aux{@ext} = 1; + @ext = keys %aux; + undef %aux; @aux{@myjars} = (1) x ($#myjars+1); + @myjars = keys %aux; + + print "\nRequired externals:\n"; + print "\t$_: $extern_prefix{$_}\n" for @ext; + print "\t$_: $jar{$_}\n" for @myjars; + print "\nThis is a poor-man configure, it's up to you to have sources and externals there\n\n"; + + mkinc($_) for @modules; + + print "Creating Makefile\n"; + + open MAK,">Makefile" or die "Makefile: $!\n"; + + print MAK "all: @modules\n\nclean:\n"; + + for (@modules) { + my $full = full($_); + print MAK "\tcd $full/$buildroot{$_} && \${MAKE} clean\n" + } + + print MAK "\ndistclean:\n"; + + for (@modules) { + my $full = full($_); + print MAK $buildroot{$_} eq '' ? + "\tcd $full && \${MAKE} distclean\n" : + "\trm -rf $full/$buildroot{$_}\n" + } + + print MAK "\n"; + + for (@modules) { + my %ldeps; undef %ldeps; + @ldeps{@{$deps{$_}}} = 1; + for my $x (split /,/,$staged) { delete $ldeps{$x}; } + my @dnames = $module ? () : keys %ldeps; + + my $full = full($_); + my $build = $buildroot{$_}; + + print MAK "$_: @dnames\n\tcd $full/$build && \${MAKE} && \${MAKE} install\n\n"; + } + + close MAK; +} + +sub mode_checkout() { + for (@modules) { + my $module = $_; + my $tag = ""; + if ($lb_tag){ + for (@{$lbmodules{lb}}){ + if ("lb.".$_ eq $module){ + $tag = '-r '.$lb_tag; + } + } + } + if ($lbjp_tag){ + for (@{$lbmodules{'lbjp-common'}}){ + if ("lbjp-common.".$_ eq $module){ + $tag = '-r '.$lbjp_tag; + } + } + } + if ($jp_tag){ + for (@{$lbmodules{'jp'}}){ + if ("jp.".$_ eq $module){ + $tag = '-r '.$jp_tag; + } + } + } + if ($sec_tag){ + for (@{$lbmodules{security}}){ + if ("security.".$_ eq $module){ + $tag = '-r '.$sec_tag; + } + } + } + if ($jobid_tag){ + for (@{$lbmodules{jobid}}){ + if ("jobid.".$_ eq $module){ + $tag = '-r '.$jobid_tag; + } + } + } + #if (grep {"lb.".$_ eq $module} @{$lbmodules{lb}}){ + # print "found"; + #} + $_ = full($_); + print "\n*** Checking out $_\n"; + system("cvs checkout $tag $_") == 0 or die "cvs checkout $tag $_: $?\n"; + } +} + +BEGIN{ +%need_externs_aux = ( + 'lb.client' => [ qw/cppunit:B classads/ ], + 'lb.client-java' => [ qw/ant:B jdk:B axis:B trustmanager utiljava/ ], + 'lb.common' => [ qw/expat cares:B cppunit:B classads/ ], + 'lb.doc' => [], + 'lb.logger' => [ qw/cppunit:B/ ], + 'lb.server' => [ qw/globus_essentials:R globus:B expat cares mysql:R mysql-server:R mysql-devel:B cppunit:B gsoap:B classads voms lcas gridsite/ ], + 'lb.state-machine' => [ qw/classads/ ], + 'lb.utils' => [ qw/cppunit:B/ ], + 'lb.ws-interface' => [], + 'lb.ws-test' => [ qw/gsoap:B/ ], + 'lb.types' => [ qw// ], + 'lb.harvester' => [ qw// ], + 'lb.yaim' => [ qw/yaim_core:R/ ], + 'lb.glite-LB' => [ qw/fetchcrl:R gpt:R gip_release:R gip_service:R bdii:R glite_version:R glite_info_templates:R glue_schema:R/ ], + 'lbjp-common.db' => [ qw/mysql:B mysql-devel:B postgresql:B cppunit:B log4c:B/ ], + 'lbjp-common.log' => [ qw/log4c/ ], + 'lbjp-common.maildir' => [ qw// ], + 'lbjp-common.server-bones' => [ qw// ], + 'lbjp-common.trio' => [ qw/cppunit:B/ ], + 'lbjp-common.jp-interface' => [ qw/cppunit:B log4c:B/ ], + 'security.gss' => [ qw/globus_essentials:R globus:B cares cppunit:B/ ], + 'security.gsoap-plugin' => [ qw/cppunit:B globus_essentials:R globus:B cares:B gsoap:B/ ], + 'jobid.api-c' => [ qw/cppunit:B/ ], + 'jobid.api-cpp' => [ qw/cppunit:B/ ], + 'jobid.api-java' => [ qw/ant:B jdk:B/ ], + 'jp.client' => [ qw/gsoap libtar globus_essentials:R globus:B/ ], + 'jp.doc' => [], + 'jp.index' => [ qw/gsoap globus_essentials:R globus:B/ ], + 'jp.primary' => [ qw/classads gsoap libtar globus_essentials:R globus:B/ ], + 'jp.server-common' => [], + 'jp.ws-interface' => [], + 'gridsite.core' => [qw/httpd-devel:B gsoap:B globus:B/ ], +); + +for my $ext (keys %need_externs_aux) { + for (@{$need_externs_aux{$ext}}) { + /([^:]*)(?::(.*))?/; + push @{$need_externs{$ext}},$1; + my $type = $2 ? $2 : 'BR'; + $need_externs_type{$ext}->{$1} = $type; + } +} + +%need_jars = ( + 'jobid.api-java' => [ qw/commons-codec/ ], + 'lb.client-java' => [ qw/commons-lang/ ], +); + +for my $jar (keys %need_jars) { + for (@{$need_jars{$jar}}) { + $need_externs_type{$jar}->{$_} = 'BR'; # XXX + } +} + +%deps_aux = ( + 'lb.client' => [ qw/ + lb.types:B lb.common + lbjp-common.trio + jobid.api-cpp:B jobid.api-c + security.gss + / ], + 'lb.client-java' => [ qw/ + lb.types:B + lb.ws-interface:B + jobid.api-java + / ], + 'lb.common' => [ qw/ + jobid.api-cpp:B jobid.api-c + lb.types:B lbjp-common.trio security.gss + / ], + 'lb.doc' => [ qw/lb.types:B/ ], + 'lb.logger' => [ qw/ + lbjp-common.trio + lbjp-common.log + jobid.api-c + lb.common + security.gss + / ], + 'lb.server' => [ qw/ + lb.ws-interface lb.types:B lb.common lb.state-machine + lbjp-common.db lbjp-common.server-bones lbjp-common.trio lbjp-common.maildir lbjp-common.log + jobid.api-c + security.gsoap-plugin security.gss + / ], + 'lb.state-machine' => [ qw/lb.types:B lb.common lbjp-common.jp-interface security.gss/ ], + 'lb.utils' => [ qw/ + lbjp-common.jp-interface + jobid.api-c + lbjp-common.trio lbjp-common.maildir + lb.client lb.state-machine + / ], + 'lb.ws-test' => [ qw/security.gsoap-plugin lb.ws-interface/ ], + 'lb.ws-interface' => [ qw/lb.types:B/ ], + 'lb.types' => [ qw// ], + 'lb.harvester' => [ qw/ + jobid.api-c lbjp-common.trio lbjp-common.db lb.common lb.client + security.gss lbjp-common.log + / ], + 'lb.yaim' => [ qw// ], + 'lb.glite-LB' => [ qw/ + lb.logger:R lb.server:R lb.utils:R lb.doc:R + lb.ws-test:R lb.harvester:R lb.yaim:R lb.client-java:R + / ], + 'lbjp-common.db' => [ qw/lbjp-common.trio lbjp-common.log/ ], + 'lbjp-common.maildir' => [ qw// ], + 'lbjp-common.log' => [ qw// ], + 'lbjp-common.server-bones' => [ qw/lbjp-common.log/ ], + 'lbjp-common.trio' => [ qw// ], + 'security.gss' => [ qw// ], + 'security.gsoap-plugin' => [ qw/security.gss/ ], + 'jobid.api-c' => [ qw// ], + 'jobid.api-cpp' => [ qw/jobid.api-c/ ], + 'jobid.api-java' => [ qw// ], + + 'lbjp-common.jp-interface' => [ qw/lbjp-common.db jobid.api-c/ ], + + 'jp.client' => [ qw/ + jp.ws-interface + lbjp-common.jp-interface lbjp-common.maildir + jobid.api-c + security.gsoap-plugin + / ], + 'jp.doc' => [ qw// ], + 'jp.index' => [ qw/ + jp.server-common jp.ws-interface + lbjp-common.jp-interface lbjp-common.trio lbjp-common.db lbjp-common.server-bones + security.gsoap-plugin + / ], + 'jp.primary' => [ qw/ + jobid.api-c + jp.server-common jp.ws-interface + lb.state-machine + lbjp-common.jp-interface lbjp-common.trio lbjp-common.db lbjp-common.server-bones + security.gsoap-plugin + / ], + 'jp.server-common' => [ qw/ + lbjp-common.jp-interface lbjp-common.db + / ], + 'jp.ws-interface' => [ qw// ], + + 'gridsite.core' => [ qw/build.common-cpp:B/ ], +); + +for my $ext (keys %deps_aux) { + for (@{$deps_aux{$ext}}) { + /([^:]*)(?::(.*))?/; + push @{$deps{$ext}},$1; + my $type = $2 ? $2 : 'BR'; + $deps_type{$ext}->{$1} = $type; + } +} + + +%extrafull = ( gridsite=>'org.gridsite.core'); + +#( java => 'client-java' ); +%extranodmod = ( + db => 'lbjp-common.db', + jpprimary => 'jp.primary', + jpindex => 'jp.index', + jpclient => 'jp.client', +); + +%obsoletes = ( + 'lb.yaim' => [ qq/glite-yaim-lb/ ], +); + +%cvs_prefix = ( + 'lb' => 'org.glite', + 'jp' => 'org.glite', + 'jobid' => 'org.glite', + 'lbjp-common' => 'org.glite', + 'gridsite' => 'org', + 'security' => 'org.glite', +); + +%conf_prefix = ( + 'lb' => 'glite-', + 'jp' => 'glite-', + 'jobid' => 'glite-', + 'lbjp-common' => 'glite-', + 'gridsite' => '', + 'security' => 'glite-', +); + +my @k = keys %deps_aux; +@buildroot{@k} = ('build') x ($#k+1); + +my @t = qw/lb.client-java jobid.api-java lb.types/; +@buildroot{@t} = ('') x ($#t+1); + +$buildroot{'gridsite.core'} = 'src'; +} + +sub full +{ + my $short = shift; + return $extrafull{$short} ? $extrafull{$short} : 'org.glite.'.$short; +} + +sub mkinc +{ + my %aux; + undef %aux; + my @m=qw/ +lb.client lb.doc lb.state-machine lb.ws-interface lb.logger lb.types lb.common lb.server lb.utils lb.ws-test lb.client-java lb.harvester lb.yaim lb.glite-LB +security.gss security.gsoap-plugin +jobid.api-c jobid.api-cpp jobid.api-java +lbjp-common.db lbjp-common.log lbjp-common.maildir lbjp-common.server-bones lbjp-common.trio lbjp-common.jp-interface +jp.client jp.doc jp.index jp.primary jp.server-common jp.ws-interface +/; + @aux{@m} = (1) x ($#m+1); + + my $short = shift; + my $full = full $short; + + unless ($aux{$short}) { + print "Makefile.inc not needed in $full\n"; + return; + } + + my $build = ''; + + unless ($buildroot{$_} eq '') { + $build = "/$buildroot{$_}"; + unless (-d "$full/$buildroot{$_}") { + mkdir "$full/$buildroot{$_}" or die "mkdir $full/$buildroot{$_}: $!\n"; + } + unlink "$full/$buildroot{$_}/Makefile"; + symlink "../Makefile","$full/$buildroot{$_}/Makefile" or die "symlink ../Makefile $full/$buildroot{$_}/Makefile: $!\n"; + } + + open MKINC,">$full/$buildroot{$_}/Makefile.inc" + or die "$full/$buildroot{$_}/Makefile.inc: $!\n"; + + print "Creating $full/$buildroot{$_}/Makefile.inc\n"; + + print MKINC qq{ +PREFIX = $prefix +stagedir = $stagedir +thrflavour = $thrflavour +nothrflavour = $nothrflavour +libdir = $libdir +}; + + for (@{$need_externs{$short}}) { + print MKINC "${_}_prefix = $extern_prefix{$_}\n" + } + + for (@{$need_jars{$short}}) { + print MKINC "${_}_jar = $jar{$_}\n" + } + + my $need_gsoap = 0; + for (@{$need_externs{$short}}) { $need_gsoap = 1 if $_ eq 'gsoap'; } + + print MKINC "gsoap_default_version=".gsoap_version()."\n" if $need_gsoap; + + close MKINC; +} + +my %etics_externs; +my %etics_projects; +BEGIN{ + %etics_externs = ( + globus_essentials=>'vdt_globus_essentials', + globus=>'globus', + cares=>'c-ares', + voms=>'org.glite.security.voms-api-cpp', + gridsite=>'org.gridsite.shared', + lcas=>'org.glite.security.lcas', + trustmanager=>'org.glite.security.trustmanager', + utiljava=>'org.glite.security.util-java', + gpt=>'gpt', + fetchcrl=>'fetch-crl', + gip_release=>'glite-info-provider-release', + gip_service=>'glite-info-provider-service', + bdii=>'bdii', + glite_version=>'glite-version', + glite_info_templates=>'glite-info-templates', + glue_schema=>'glue-schema', + yaim_core=>'org.glite.yaim.core', + ); + %etics_projects = ( + vdt=>[qw/globus globus_essentials/], + 'org.glite'=>[qw/voms gridsite lcas gpt gip_release gip_service bdii glite_version glite_info_templates glue_schema yaim_core/], + ); + + %platform_properties = ( + 'gridsite.core' => { + sl5_x86_64_gcc412 => { aprSuffix => '1' }, + sl5_ia32_gcc412 => { aprSuffix => '1' }, + deb5_x86_64_gcc432 => { aprSuffix => '1.0' }, + deb5_ia32_gcc432 => { aprSuffix => '1.0' }, + slc4_x86_64_gcc346 => { aprSuffix => '0' }, + slc4_ia32_gcc346 => { aprSuffix => '0' }, + default => { + } + }, + ); +}; + +sub mode_etics { + $fmod = shift; + + die "$0: --module required with --etics\n" unless $fmod; + + my ($subsys,$module) = split /\./,$fmod; + + my ($major,$minor,$rev,$age); + + if ($version) { + $version =~ /([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)-(.+)/; + ($major,$minor,$rev,$age) = ($1,$2,$3,$4); + } + else { + open V,"$cvs_prefix{$subsys}.$subsys.$module/project/version.properties" + or die "$cvs_prefix{$subsys}.$subsys.$module/project/version.properties: $!\n"; + + while ($_ = ) { + chomp; + ($major,$minor,$rev) = ($1,$2,$3) if /module\.version\s*=\s*([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)/; + $age = $1 if /module\.age\s*=\s*([[:digit:]]+)/; + } + close V; + } + + my @copts = (); + my %ge; + @ge{@{$etics_projects{'org.glite'}}} = (1) x ($#{$etics_projects{'org.glite'}}+1); + + for (@{$need_externs{"$subsys.$module"}}) { + if ($need_externs_type{"$subsys.$module"}->{$_}=~/B/) { + my $eext = $etics_externs{$_} ? $etics_externs{$_} : $_; + push @copts,$ge{$_} ? "--with-$_=\${stageDir}" : "--with-$_=\${$eext.location}"; + } + } + + for (@{$need_jars{"$subsys.$module"}}) { + my $eext = $etics_externs{$_} ? $etics_externs{$_} : $_; + + push @copts,"--with-$_ \${$eext.location}/$_*.jar"; + } + + my $conf; + my $conftag; + + $dwpath = "path = \${projectName}/\${moduleName}/\${version}/\${platformName}/\${packageName}-\${version}-\${age}.tar.gz\n"; + if ($branch) { + $conf = "$conf_prefix{$subsys}${subsys}-${module}_$branch"; + $conftag = $branch; + $age = '0dev'; } + else { + $conf = "$conf_prefix{$subsys}$subsys-${module}_R_${major}_${minor}_${rev}_${age}"; + +# XXX: gridsite hack + $conftag = $subsys eq 'gridsite' ? "$conf_prefix{$subsys}$subsys-${module}_R_${major}_${minor}_${rev}" : $conf; } + my $file = $output ? $output : "$conf.ini"; + open C,">$file" or die "$file: $!\n"; + + my $buildroot = $buildroot{"$subsys.$module"} eq '' ? '#no build.root' : "build.root = " . $buildroot{"$subsys.$module"}; + + my $confdir = $buildroot{"$subsys.$module"} eq '' ? '..' : '../..'; + + my $package_description = ""; + my $package_summary = ""; + + if (-e "$cvs_prefix{$subsys}.$subsys.$module/project/package.description") { + open V, "$cvs_prefix{$subsys}.$subsys.$module/project/package.description"; + $package_description = join ("", ); + close V; + chomp $package_description; + $package_description =~ s/\n/\\n/g; + $package_description = "package.description = $package_description\n"; + } + else { + print STDERR "package.description not found for $subsys.$module!\n"; } + + if (-e "$cvs_prefix{$subsys}.$subsys.$module/project/package.summary") { + open V, "$cvs_prefix{$subsys}.$subsys.$module/project/package.summary"; + $package_summary = join ("", ); + close V; + chomp $package_summary; + $package_summary =~ s/\n/\\n/g; + $package_summary = "package.summary = $package_summary\n"; + } + else { + print STDERR "package.summary not found for $subsys.$module!\n"; } + + my %cmd; + @cmd{qw/configure compile test install packaging clean/} = ('None') x 6; + $cmd{clean} = 'make clean'; + + if ($subsys eq 'gridsite') { + if ($module eq 'core') { + my $flags = 'RELEASE_VERSION=${age}.${platformFamily} prefix=${prefix} libdir=${libdir} GSOAPDIR=${gsoap.location} OPENSSL_GLOBUS_FLAGS=-I${globus.location}/include/${globus.dbg.nothr.flavor} OPENSSL_GLOBUS_LIBS=-L${globus.location}/${libdir}/ FLAVOR_GLOBUS_EXT=_${globus.dbg.nothr.flavor} HTTPD_FLAGS="-I${httpd-devel.location}/include/httpd -I${httpd-devel.location}/include/apache2 -I${httpd-devel.location}/include/apr-${aprSuffix} -I${httpd-devel.location}/include/pcre"'; + + $cmd{compile} = "make $flags build"; + $cmd{install} = "make $flags install"; + $cmd{packaging} = "make $flags rpm"; + } + else { + $cmd{packaging} = "echo building nothing, org.gridsite.core make rpm step will create this"; + } + } + else { + $cmd{configure} = "cd $confdir && /usr/bin/perl \${moduleName}/configure --thrflavour=\${globus.thr.flavor} --nothrflavour=\${globus.nothr.flavor} --prefix=\${prefix} --stage=\${stageDir} --libdir=\${libdir} --module $subsys.$module @copts"; + $cmd{compile} = 'make'; + $cmd{test} = 'make check'; + $cmd{install} = 'make install'; + } + + my $defprops = ''; + + for my $p (keys %{$platform_properties{"$subsys.$module"}->{default}}) { + $defprops .= $p . ' = ' . $platform_properties{"$subsys.$module"}->{default}->{$p} . "\n"; + } + + print STDERR "Writing $file\n"; + print C qq{ +[Configuration-$conf] +profile = None +moduleName = $cvs_prefix{$subsys}.$subsys.$module +displayName = $conf +description = $cvs_prefix{$subsys}.$subsys.$module +projectName = org.glite +age = $age +deploymentType = None +tag = $conftag +version = $major.$minor.$rev +$dwpath +[Platform-default:VcsCommand] +displayName = None +description = None +tag = cvs -d \${vcsroot} tag -R \${tag} \${moduleName} +branch = None +commit = None +checkout = cvs -d \${vcsroot} co -r \${tag} \${moduleName} + +[Platform-default:BuildCommand] +postpublish = None +packaging = $cmd{packaging} +displayName = None +description = None +doc = None +prepublish = None +publish = None +compile = $cmd{compile} +init = None +install = $cmd{install} +clean = $cmd{clean} +test = $cmd{test} +configure = $cmd{configure} +checkstyle = None + +[Platform-default:Property] +$buildroot +aprSuffix = 0 +package.RPMSLocation = \${moduleDir}/RPMTMP/RPMS +package.SRPMSLocation = \${moduleDir}/RPMTMP/SRPMS +$package_description$package_summary$defprops +}; + for (@{$obsoletes{"$subsys.$module"}}) { + print C "package.obsoletes = $_\n"; + print C "package.replaces = $_\n"; + } + + for my $pp (keys %{$platform_properties{"$subsys.$module"}}) { + next if $pp eq 'default'; + print C "[Platform-$pp:Property]\n$buildroot\n"; + + for my $p (keys %{$platform_properties{"$subsys.$module"}->{$pp}}) { + print C $p . ' = ' . $platform_properties{"$subsys.$module"}->{$pp}->{$p} . "\n"; + } + print C q{package.RPMSLocation = ${moduleDir}/RPMTMP/RPMS +package.SRPMSLocation = ${moduleDir}/RPMTMP/SRPMS +}; + print C "$package_description$package_summary\n"; + } + + print C qq{ +[Platform-default:DynamicDependency] +}; + for (@{$need_externs{"$subsys.$module"}},@{$need_jars{"$subsys.$module"}}) { + my $eext = $etics_externs{$_} ? $etics_externs{$_} : $_; + + my $proj = 'externals'; + for my $p (keys %etics_projects) { + for $m (@{$etics_projects{$p}}) { + $proj = $p if $m eq $_; + } + } + + my $type = $need_externs_type{"$subsys.$module"}->{$_}; + print C "$proj|$eext = $type\n"; + } + + for (@{$deps{"$subsys.$module"}}) { + my $type = $deps_type{"$subsys.$module"}->{$_}; + print C "org.glite|org.glite.$_ = $type\n"; + } + + close C; +} + +sub gsoap_version { + local $_; + my $gsoap_version; + open S,"$extern_prefix{gsoap}/bin/soapcpp2 -v 2>&1 |" or die "$extern_prefix{gsoap}/bin/soapcpp2: $!\n"; + + while ($_ = ) { + chomp; + + $gsoap_version = $1 if /The gSOAP Stub and Skeleton Compiler for C and C\+\+ ([.[:digit:][:alpha:]]+)$/; + } + close S; + return $gsoap_version; +} + +sub getlibdir { + if ( -e "/etc/debian_version") { # We are on Debian + $lib64="lib"; + $lib32="lib32"; } + else { # Another distribution + $lib64="lib64"; + $lib32="lib"; } + $libdir=$lib32; + + open INP, "uname -s | "; # Check kernel name + $kname= ; + chomp($kname); + close INP; + + if ( $kname == "Linux") { + $arch = ("x86_64\npowerpc\nppc64\n"); + + open INP, "uname -p | "; # Check processor type + $procname= ; + chomp($procname); + close INP; + + if ($arch =~/^$procname\n/) { + return ($lib64); } + + open INP, "uname -m | "; # Check machine hardware + $machname= ; + chomp($machname); + close INP; + + if ($arch =~/^$machname\n/) { + return ($lib64); } + + # special cases (hyperlink lib64, Debian) + if (-l "/usr/lib64") { + $libdir=$lib32; } + + # if /usr/lib64 doesn't exist at all (AIX) + unless ( -e "/usr/lib64" ) { + $libdir=$lib32; } + } + + if ( $kname == "SunOS") { + if (-e "/usr/lib/64") { + $libdir="lib/64"; } + } + + return $libdir; +} + +sub usage { + my @ext = keys %extern_prefix; + my @myjars, keys %jar; + + print STDERR qq{ +usage: $0 options + +General options (defaults in []): + --prefix=PREFIX destination directory [./stage] + --staged=module,module,... what is already in PREFIX (specify without org.glite.) + --thrflavour=flavour + --nothrflavour=flavour threaded and non-treaded flavours [gcc64dbgpthr,gcc64dbg] + --listmodules=subsys list modules of a subsystem + --libdir=libdir typically [lib,lib64] postfix + +Mode of operation: + --mode={checkout|build|etics} what to do [build] + +What to build: + --module=module build this module only (mostly in-Etics operation) + --enable-NODE build this "node" (set of modules) only. Available nodes are + @{$lbmodules{lb}},@{$lbmodules{security}} + --disable-NODE don't build this node + --lb-tag=tag checkout LB modules with specific tag + --jp-tag=tag checkout JP modules with specific tag + --lbjp-common-tag=tag checkout lbjp-common modules with specific tag + --security-tag=tag checkout security modules with specific tag + --jobid-tag=tag checkout jobid modules with specific tag + +Dependencies: + --with-EXTERNAL=PATH where to look for an external. Required externals + (not all for all modules) are: + @ext + --with-JAR=JAR where to look for jars. Required jars are: + @myjars + Summary of what will be used is always printed + +}; + +} diff --git a/org.glite.lbjp-common.gsoap-plugin/examples/calc.h.S b/org.glite.lbjp-common.gsoap-plugin/examples/calc.h.S new file mode 100644 index 0000000..da6ea9f --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/examples/calc.h.S @@ -0,0 +1,13 @@ +//gsoap wscalc service name: CalcService +//gsoap wscalc service type: Calc +//gsoap wscalc service port: https://localhost:19999/ +//gsoap wscalc service namespace: urn:calc:wscalc +//gsoap wscalc service documentation: Calculator service + +//gsoap wscalc service method-documentation: add Adds two numbers +int wscalc__add(double a, double b, struct wscalc__addResponse { +double result; } * ); + +//gsoap wscalc service method-documentation: sub Subtracts two numbers +int wscalc__sub(double a, double b, struct wscalc__subResponse { +double result; } * ); diff --git a/org.glite.lbjp-common.gsoap-plugin/examples/wscalc_clt_ex.c b/org.glite.lbjp-common.gsoap-plugin/examples/wscalc_clt_ex.c new file mode 100644 index 0000000..a9e122d --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/examples/wscalc_clt_ex.c @@ -0,0 +1,69 @@ +/* +Copyright (c) Members of the EGEE Collaboration. 2004-2010. +See http://www.eu-egee.org/partners for details on the copyright holders. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include + +#include "GSOAP_H.h" +#include "CalcService.nsmap" + +static const char *server = "http://localhost:19999/"; + +int +main(int argc, char **argv) +{ + struct soap soap; + double a, b, result; + int ret; + struct wscalc__addResponse addresult; + struct wscalc__subResponse subresult; + + + if (argc < 4) { + fprintf(stderr, "Usage: [add|sub] num num\n"); + exit(1); + } + + soap_init(&soap); + soap_set_namespaces(&soap, namespaces); + soap_register_plugin(&soap, glite_gsplugin); + + a = strtod(argv[2], NULL); + b = strtod(argv[3], NULL); + switch ( *argv[1] ) { + case 'a': + ret = soap_call_wscalc__add(&soap, server, "", a, b, &addresult); + result = addresult.result; + break; + case 's': + ret = soap_call_wscalc__sub(&soap, server, "", a, b, &subresult); + result = subresult.result; + break; + default: + fprintf(stderr, "Unknown command\n"); + exit(2); + } + + if ( ret ) { + fprintf(stderr, "NECO JE V ****\n\n"); + fprintf(stderr, "plugin err: %s", glite_gsplugin_errdesc(&soap)); + soap_print_fault(&soap, stderr); + } + else printf("result = %g\n", result); + + + return 0; +} diff --git a/org.glite.lbjp-common.gsoap-plugin/examples/wscalc_srv_ex.c b/org.glite.lbjp-common.gsoap-plugin/examples/wscalc_srv_ex.c new file mode 100644 index 0000000..975afa8 --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/examples/wscalc_srv_ex.c @@ -0,0 +1,128 @@ +/* +Copyright (c) Members of the EGEE Collaboration. 2004-2010. +See http://www.eu-egee.org/partners for details on the copyright holders. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include +#include +#include +#include + +#include "GSOAP_H.h" +#include "CalcService.nsmap" + + +static struct option long_options[] = { + { "cert", required_argument, NULL, 'c' }, + { "key", required_argument, NULL, 'k' }, + { NULL, 0, NULL, 0 } +}; + +void +usage(const char *me) +{ + fprintf(stderr, + "usage: %s [option]\n" + "\t-c, --cred\t certificate file\n" + "\t-k, --key\t private key file\n", me); +} + + +int +main(int argc, char **argv) +{ + struct soap soap; + glite_gsplugin_Context ctx = NULL; + char *name; + char *cert, *key; + int opt; + edg_wll_GssCred cred; + + cert = key = NULL; + name = strrchr(argv[0],'/'); + if ( name ) name++; else name = argv[0]; + + while ((opt = getopt_long(argc, argv, "c:k:", long_options, NULL)) != EOF) { + switch (opt) { + case 'c': cert = optarg; break; + case 'k': key = optarg; break; + case '?': + default : usage(name); exit(1); + } + } + + soap_init(&soap); + soap_set_namespaces(&soap, namespaces); + + if ( soap_register_plugin_arg(&soap, glite_gsplugin, NULL) ) { + fprintf(stderr, "Can't register plugin\n"); + exit(1); + } + + if ( cert || key ) { + ctx = glite_gsplugin_get_context(&soap); + if (ctx == NULL) { + fprintf(stderr, "Can't get context\n"); + exit(1); + } + + if (glite_gsplugin_set_credential(ctx, cert, key) != 0) { + fprintf(stderr, "Can't set credentials: %s\n", + glite_gsplugin_errdesc(&soap)); + exit(1); + } + } + + if ( soap_bind(&soap, NULL, 19999, 100) < 0 ) { + soap_print_fault(&soap, stderr); + exit(1); + } + + while ( 1 ) { + printf("accepting connection\n"); + if ( soap_accept(&soap) < 0 ) { + fprintf(stderr, "soap_accept() failed!!!\n"); + soap_print_fault(&soap, stderr); + fprintf(stderr, "plugin err: %s\n", glite_gsplugin_errdesc(&soap)); + continue; + } + + printf("serving connection\n"); + if ( soap_serve(&soap) ) { + soap_print_fault(&soap, stderr); + fprintf(stderr, "plugin err: %s", glite_gsplugin_errdesc(&soap)); + } + + soap_destroy(&soap); /* clean up class instances */ + soap_end(&soap); /* clean up everything and close socket */ + } + soap_done(&soap); /* close master socket */ + + if ( ctx ) glite_gsplugin_free_context(ctx); + + return 0; +} + +int wscalc__add(struct soap *soap, double a, double b, struct wscalc__addResponse *result) +{ + result->result = a + b; + return SOAP_OK; +} + +int wscalc__sub(struct soap *soap, double a, double b, struct wscalc__subResponse *result) +{ + result->result = a - b; + return SOAP_OK; +} diff --git a/org.glite.lbjp-common.gsoap-plugin/examples/wscalc_srv_ex2.c b/org.glite.lbjp-common.gsoap-plugin/examples/wscalc_srv_ex2.c new file mode 100644 index 0000000..3bec28a --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/examples/wscalc_srv_ex2.c @@ -0,0 +1,167 @@ +/* +Copyright (c) Members of the EGEE Collaboration. 2004-2010. +See http://www.eu-egee.org/partners for details on the copyright holders. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include +#include +#include +#include +#include + +#include "GSOAP_H.h" +#include "CalcService.nsmap" + + +static struct option long_options[] = { + { "cert", required_argument, NULL, 'c' }, + { "key", required_argument, NULL, 'k' }, + { "port", required_argument, NULL, 'p' }, + { NULL, 0, NULL, 0 } +}; + +void +usage(const char *me) +{ + fprintf(stderr, + "usage: %s [option]\n" + "\t-p, --port\t listening port\n" + "\t-c, --cred\t certificate file\n" + "\t-k, --key\t private key file\n", me); +} + + +int +main(int argc, char **argv) +{ + struct soap soap; + edg_wll_GssStatus gss_code; + edg_wll_GssCred cred = NULL; + edg_wll_GssConnection connection; + glite_gsplugin_Context ctx; + struct sockaddr_storage a; + int alen; + char *name, *msg; + int opt, + port = 19999; + char *cert_filename = NULL, *key_filename = NULL; + int sock; + struct addrinfo hints; + struct addrinfo *res; + char *portname; + int error; + + name = strrchr(argv[0],'/'); + if ( name ) name++; else name = argv[0]; + + if ( glite_gsplugin_init_context(&ctx) ) { perror("init context"); exit(1); } + + while ((opt = getopt_long(argc, argv, "c:k:p:", long_options, NULL)) != EOF) { + switch (opt) { + case 'p': port = atoi(optarg); break; + case 'c': cert_filename = strdup(optarg); break; + case 'k': key_filename = strdup(optarg); break; + case '?': + default : usage(name); exit(1); + } + } + + if ( edg_wll_gss_acquire_cred_gsi(cert_filename, key_filename, &cred, &gss_code) ) { + edg_wll_gss_get_error(&gss_code, "Failed to read credential", &msg); + fprintf(stderr, "%s\n", msg); + free(msg); + exit(1); + } + if (cred->name) { + printf("server running with certificate: %s\n", cred->name); + } + + glite_gsplugin_use_credential(ctx, cred); + + soap_init(&soap); + soap_set_namespaces(&soap, namespaces); + + if ( soap_register_plugin_arg(&soap, glite_gsplugin, ctx) ) { + fprintf(stderr, "Can't register plugin\n"); + exit(1); + } + + asprintf(&portname, "%d", port); + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_flags = AI_PASSIVE; + hints.ai_socktype = SOCK_STREAM; + error = getaddrinfo(NULL, portname , &hints, &res); + if (error) { + perror(gai_strerror(error)); + exit(1); + } + alen = res->ai_addrlen; + if ( (sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) < 0 ) + { perror("socket()"); exit(1); } + if ( bind(sock, res->ai_addr, res->ai_addrlen) ) { perror("bind()"); exit(1); } + freeaddrinfo(res); + if ( listen(sock, 100) ) { perror("listen()"); exit(1); } + + bzero((char *) &a, alen); + + while ( 1 ) { + int conn; + + printf("accepting connection\n"); + if ( (conn = accept(sock, (struct sockaddr *) &a, &alen)) < 0 ) { + close(sock); + perror("accept"); + exit(1); + } + if ( edg_wll_gss_accept(cred,conn,ctx->timeout,&connection,&gss_code) ){ + edg_wll_gss_get_error(&gss_code, "Failed to read credential", &msg); + fprintf(stderr, "%s\n", msg); + free(msg); + exit(1); + } + + glite_gsplugin_set_connection(ctx, &connection); + + printf("serving connection\n"); + if ( soap_serve(&soap) ) { + soap_print_fault(&soap, stderr); + fprintf(stderr, "plugin err: %s", glite_gsplugin_errdesc(&soap)); + } + + soap_destroy(&soap); /* clean up class instances */ + soap_end(&soap); /* clean up everything and close socket */ + edg_wll_gss_close(&connection, NULL); + } + + soap_done(&soap); /* close master socket */ + + glite_gsplugin_free_context(ctx); + edg_wll_gss_release_cred(&cred, NULL); + + return 0; +} + +int wscalc__add(struct soap *soap, double a, double b, struct wscalc__addResponse *result) +{ + result->result = a + b; + return SOAP_OK; +} + +int wscalc__sub(struct soap *soap, double a, double b, struct wscalc__subResponse *result) +{ + result->result = a - b; + return SOAP_OK; +} diff --git a/org.glite.lbjp-common.gsoap-plugin/interface/glite_gscompat.h b/org.glite.lbjp-common.gsoap-plugin/interface/glite_gscompat.h new file mode 100644 index 0000000..50a2b93 --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/interface/glite_gscompat.h @@ -0,0 +1,111 @@ +/* +Copyright (c) Members of the EGEE Collaboration. 2004-2010. +See http://www.eu-egee.org/partners for details on the copyright holders. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#ifndef GLITE_SECURITY_GSCOMPAT_H +#define GLITE_SECURITY_GSCOMPAT_H + +#ident "$Header: " + +#ifndef GSOAP_VERSION + #error GSOAP_VERSION required +#endif + +#ifndef GSOAP_VERSION_LETTER +#define GSOAP_VERSION_LETTER '\0' +#endif + +#if GSOAP_VERSION >= 20709 || GSOAP_VERSION == 20706 && GSOAP_VERSION_LETTER >= 'd' + #define GLITE_SECURITY_GSOAP_CHOICE_GET(CHOICE, ITEM, TYPENAME, TYPENO) ((CHOICE)->union_##TYPENAME.ITEM) + #define GLITE_SECURITY_GSOAP_CHOICE_SETTYPE(CHOICE, ITEM, NS, TYPENAME, TYPENO) ((CHOICE)->__union_##TYPENAME) = SOAP_UNION__##NS##__union_##TYPENAME##_##ITEM + #define GLITE_SECURITY_GSOAP_CHOICE_ISTYPE(CHOICE, ITEM, NS, TYPENAME, TYPENO) (((CHOICE)->__union_##TYPENAME) == SOAP_UNION__##NS##__union_##TYPENAME##_##ITEM) + /** 2.7.10 requires created dummy choice with type == 0 for empty optional choice */ + #if GSOAP_VERSION >= 20710 + #define GLITE_SECURITY_GSOAP_CHOICE_SETNULL(CHOICE, TYPENAME) ((CHOICE)->__union_##TYPENAME) = 0 + #endif +#elif GSOAP_VERSION >= 20706 + #define GLITE_SECURITY_GSOAP_CHOICE_GET(CHOICE, ITEM, TYPENAME, TYPENO) ((CHOICE)->union_##TYPENO.ITEM) + #define GLITE_SECURITY_GSOAP_CHOICE_SETTYPE(CHOICE, ITEM, NS, TYPENAME, TYPENO) ((CHOICE)->__union_##TYPENO) = SOAP_UNION_##NS##__union_##TYPENO##_##ITEM + #define GLITE_SECURITY_GSOAP_CHOICE_ISTYPE(CHOICE, ITEM, NS, TYPENAME, TYPENO) (((CHOICE)->__union_##TYPENO) == SOAP_UNION_##NS##__union_##TYPENO##_##ITEM) +#else + #define GLITE_SECURITY_GSOAP_CHOICE_GET(CHOICE, ITEM, TYPENAME, TYPENO) ((CHOICE)->ITEM) + #define GLITE_SECURITY_GSOAP_CHOICE_SETTYPE(CHOICE, ITEM, NS, TYPENAME, TYPENO) + #define GLITE_SECURITY_GSOAP_CHOICE_ISTYPE(CHOICE, ITEM, NS, TYPENAME, TYPENO) (((CHOICE)->ITEM) != NULL) +#endif +#define GLITE_SECURITY_GSOAP_CHOICE_SET(CHOICE, ITEM, NS, TYPENAME, TYPENO, VALUE) do { \ + memset((CHOICE), 0, sizeof(*(CHOICE))); \ + GLITE_SECURITY_GSOAP_CHOICE_SETTYPE(CHOICE, ITEM, NS, TYPENAME, TYPENO); \ + GLITE_SECURITY_GSOAP_CHOICE_GET(CHOICE, ITEM, TYPENAME, TYPENO) = (VALUE); \ +} while(0) + +#if GSOAP_VERSION >= 20706 + #define GLITE_SECURITY_GSOAP_REASON2(SOAP) ((SOAP)->fault->SOAP_ENV__Reason ? (SOAP)->fault->SOAP_ENV__Reason->SOAP_ENV__Text : "(no reason)") + #define GLITE_SECURITY_GSOAP_TRUE xsd__boolean__true_ + #define GLITE_SECURITY_GSOAP_FALSE xsd__boolean__false_ +#else + #define GLITE_SECURITY_GSOAP_REASON2(SOAP) ((SOAP)->fault->SOAP_ENV__Reason) + #define GLITE_SECURITY_GSOAP_TRUE true_ + #define GLITE_SECURITY_GSOAP_FALSE false_ +#endif + +#define GLITE_SECURITY_GSOAP_DETAIL(SOAP) ((SOAP)->version == 2 ? (SOAP)->fault->SOAP_ENV__Detail : (SOAP)->fault->detail) +#define GLITE_SECURITY_GSOAP_REASON(SOAP) ((SOAP)->version == 2 ? GLITE_SECURITY_GSOAP_REASON2((SOAP)) : (SOAP)->fault->faultstring) + +#if GSOAP_VERSION >= 20709 + #define GLITE_SECURITY_GSOAP_LIST_CREATE0(SOAP, LIST, SIZE, TYPE, N) do { \ + if ((N) != 0) (LIST) = soap_malloc((SOAP), (N) * sizeof(TYPE)); \ + else (LIST) = NULL; \ + (SIZE) = (N); \ +} while (0) + #define GLITE_SECURITY_GSOAP_LIST_DESTROY0(SOAP, LIST, SIZE) do { \ + if ((LIST) && (SIZE) != 0) soap_dealloc((SOAP), (LIST)); \ + (LIST) = NULL; \ +} while (0) + #define GLITE_SECURITY_GSOAP_LIST_GET(LIST, INDEX) (&(LIST)[INDEX]) + #define GLITE_SECURITY_GSOAP_LIST_TYPE(NS, LIST) struct NS##__##LIST * +#else + #define GLITE_SECURITY_GSOAP_LIST_CREATE0(SOAP, LIST, SIZE, TYPE, N) do { \ + int ilist; \ + \ + if ((N) != 0) (LIST) = soap_malloc((SOAP), (N) * sizeof(void *)); \ + else (LIST) = NULL; \ + (SIZE) = (N); \ + for (ilist = 0; ilist < (N); ilist++) { \ + (LIST)[ilist] = soap_malloc((SOAP), sizeof(TYPE)); \ + } \ +} while (0) + #define GLITE_SECURITY_GSOAP_LIST_DESTROY0(SOAP, LIST, SIZE) do { \ + int ilist; \ + \ + for (ilist = 0; ilist < (SIZE); ilist++) soap_dealloc((SOAP), (LIST)[ilist]); \ + if ((LIST) && (SIZE) != 0) soap_dealloc((SOAP), (LIST)); \ + (LIST) = NULL; \ +} while (0) + #define GLITE_SECURITY_GSOAP_LIST_GET(LIST, INDEX) ((LIST)[INDEX]) + #define GLITE_SECURITY_GSOAP_LIST_TYPE(NS, LIST) struct NS##__##LIST ** +#endif +#define GLITE_SECURITY_GSOAP_LIST_CREATE(SOAP, CONTAINER, LIST, TYPE, N) GLITE_SECURITY_GSOAP_LIST_CREATE0(SOAP, (CONTAINER)->LIST, (CONTAINER)->__size##LIST, TYPE, N) +#define GLITE_SECURITY_GSOAP_LIST_DESTROY(SOAP, CONTAINER, LIST) GLITE_SECURITY_GSOAP_LIST_DESTROY0(SOAP, (CONTAINER)->LIST, (CONTAINER)->__size##LIST) + +#if GSOAP_VERSION >= 20710 + #define GLITE_SECURITY_GSOAP_SET_FIXED(soap,attr,value) \ + (attr) = soap_strdup((soap),(value)) +#else +/* XXX unsupported */ + #define GLITE_SECURITY_GSOAP_SET_FIXED(soap,attr,value) +#endif + +#endif diff --git a/org.glite.lbjp-common.gsoap-plugin/interface/glite_gsplugin-int.h b/org.glite.lbjp-common.gsoap-plugin/interface/glite_gsplugin-int.h new file mode 100644 index 0000000..a962882 --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/interface/glite_gsplugin-int.h @@ -0,0 +1,45 @@ +/* +Copyright (c) Members of the EGEE Collaboration. 2004-2010. +See http://www.eu-egee.org/partners for details on the copyright holders. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#ifndef GLITE_SECURITY_GSOAP_PLUGIN_INTERNAL_H +#define GLITE_SECURITY_GSOAP_PLUGIN_INTERNAL_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "glite/security/glite_gss.h" + +struct _glite_gsplugin_ctx { + struct timeval _timeout, *timeout; + + char *error_msg; + + edg_wll_GssConnection *connection; + edg_wll_GssCred cred; + int internal_connection; + int internal_credentials; + + void *user_data; +}; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/org.glite.lbjp-common.gsoap-plugin/interface/glite_gsplugin.h b/org.glite.lbjp-common.gsoap-plugin/interface/glite_gsplugin.h new file mode 100644 index 0000000..022a897 --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/interface/glite_gsplugin.h @@ -0,0 +1,51 @@ +/* +Copyright (c) Members of the EGEE Collaboration. 2004-2010. +See http://www.eu-egee.org/partners for details on the copyright holders. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#ifndef GLITE_SECURITY_GSOAP_PLUGIN_H +#define GLITE_SECURITY_GSOAP_PLUGIN_H + +#include + +#include "glite/security/glite_gss.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define PLUGIN_ID "GLITE_GSOAP_PLUGIN" + +typedef struct _glite_gsplugin_ctx *glite_gsplugin_Context; + +extern int glite_gsplugin_init_context(glite_gsplugin_Context *); +extern int glite_gsplugin_free_context(glite_gsplugin_Context); +extern glite_gsplugin_Context glite_gsplugin_get_context(struct soap *); +extern void *glite_gsplugin_get_udata(struct soap *); +extern void glite_gsplugin_set_udata(struct soap *, void *); + +extern void glite_gsplugin_set_timeout(glite_gsplugin_Context, struct timeval const *); +extern int glite_gsplugin_set_credential(glite_gsplugin_Context, const char *, const char *); +extern void glite_gsplugin_use_credential(glite_gsplugin_Context, edg_wll_GssCred); +extern int glite_gsplugin_set_connection(glite_gsplugin_Context, edg_wll_GssConnection *); + +extern int glite_gsplugin(struct soap *, struct soap_plugin *, void *); +extern char *glite_gsplugin_errdesc(struct soap *); + +#ifdef __cplusplus +} +#endif + +#endif /* GLITE_SECURITY_GSOAP_PLUGIN_H */ diff --git a/org.glite.lbjp-common.gsoap-plugin/project/ChangeLog b/org.glite.lbjp-common.gsoap-plugin/project/ChangeLog new file mode 100644 index 0000000..7024a4a --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/project/ChangeLog @@ -0,0 +1,45 @@ +1.5.3-1 +- avoid memleak in gsoap +- fix #32059 +- support gsoap 2.7.10 + +1.5.4-1 +- handle client connection errors in gsoap (generate faults) +- don't define gsoap.platformName in configuration confusingly + +1.5.4-2 +- disctinct c and c++ builds (concerns gsoap 2.7.10 only) + +2.0.0-1 +- LB 2.0 release + +2.0.0-2 +- configure script update (globus flavors added to configure call) + +2.0.1-1 +- API reverted towards backward compatibility + +2.0.1-2 +- Module repacked + +2.0.1-3 +- install libraries into $libdir + +2.0.2-1 +- Updated Makefile & Configure script + +2.1.0-1 +- IPv6 fixes +- Fixed error reporting +- Attempt to fix compatibility with gsoap 2.7.10 +- Improved portability + +2.1.1-1 +- libtool version numbering reintroduced + +2.1.2-1 +- Fixed target 'clean' in the Makefile to handle debian builds + +2.1.2-2 +- Module rebuilt + diff --git a/org.glite.lbjp-common.gsoap-plugin/project/build.number b/org.glite.lbjp-common.gsoap-plugin/project/build.number new file mode 100644 index 0000000..d794048 --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/project/build.number @@ -0,0 +1 @@ +module.build=0 diff --git a/org.glite.lbjp-common.gsoap-plugin/project/build.properties b/org.glite.lbjp-common.gsoap-plugin/project/build.properties new file mode 100644 index 0000000..e69de29 diff --git a/org.glite.lbjp-common.gsoap-plugin/project/configure.properties.xml b/org.glite.lbjp-common.gsoap-plugin/project/configure.properties.xml new file mode 100644 index 0000000..3977f05 --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/project/configure.properties.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + +top_srcdir=.. +builddir=build +stagedir=${stage.abs.dir} +distdir=${dist.dir} +globalprefix=${global.prefix} +lbprefix=${subsystem.prefix} +package=${module.package.name} +PREFIX=${install.dir} +version=${module.version} +glite_location=${with.glite.location} +cares_prefix=${with.c-ares.prefix} +globus_prefix=${with.globus.prefix} +thrflavour=${with.globus.thr.flavor} +nothrflavour=${with.globus.nothr.flavor} +cppunit=${with.cppunit.prefix} +gsoap_prefix=${with.gsoap.prefix} +gsoap_default_version=${ext.gsoap.version} +gsoap_name=${ext.gsoap.name} +gsoap_platform=${ext.gsoap.platform} +repository=${repository} + + + diff --git a/org.glite.lbjp-common.gsoap-plugin/project/libtoolhack/gcc b/org.glite.lbjp-common.gsoap-plugin/project/libtoolhack/gcc new file mode 100755 index 0000000..32933cd --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/project/libtoolhack/gcc @@ -0,0 +1 @@ +g++ "$@" diff --git a/org.glite.lbjp-common.gsoap-plugin/project/package.description b/org.glite.lbjp-common.gsoap-plugin/project/package.description new file mode 100644 index 0000000..ebfb912 --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/project/package.description @@ -0,0 +1 @@ +glite-security-gsoap-plugin is plugin for gSoap providing secured communication via GSS, as well as strict timing control of all operations via glite-security-gss. diff --git a/org.glite.lbjp-common.gsoap-plugin/project/package.summary b/org.glite.lbjp-common.gsoap-plugin/project/package.summary new file mode 100644 index 0000000..2f80d4f --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/project/package.summary @@ -0,0 +1 @@ +Plugin for gSoap to use glite-security-gss as the communication layer. diff --git a/org.glite.lbjp-common.gsoap-plugin/project/properties.xml b/org.glite.lbjp-common.gsoap-plugin/project/properties.xml new file mode 100755 index 0000000..f63ddbd --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/project/properties.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.glite.lbjp-common.gsoap-plugin/project/tar_exclude b/org.glite.lbjp-common.gsoap-plugin/project/tar_exclude new file mode 100644 index 0000000..b3133e4 --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/project/tar_exclude @@ -0,0 +1,10 @@ +tar_exclude +CVS +build.xml +build +build.properties +properties.xml +configure-options.xml +.cvsignore +.project +.cdtproject diff --git a/org.glite.lbjp-common.gsoap-plugin/project/version.properties b/org.glite.lbjp-common.gsoap-plugin/project/version.properties new file mode 100644 index 0000000..7838732 --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/project/version.properties @@ -0,0 +1,3 @@ +# $Header$ +module.version=2.1.2 +module.age=2 diff --git a/org.glite.lbjp-common.gsoap-plugin/src/glite_gsplugin.c b/org.glite.lbjp-common.gsoap-plugin/src/glite_gsplugin.c new file mode 100644 index 0000000..81128f4 --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/src/glite_gsplugin.c @@ -0,0 +1,594 @@ +/* +Copyright (c) Members of the EGEE Collaboration. 2004-2010. +See http://www.eu-egee.org/partners for details on the copyright holders. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "soap_version.h" +#include "glite_gsplugin-int.h" +#include "glite_gsplugin.h" + +#ifdef GSPLUGIN_DEBUG +# define pdprintf(s) printf s +#else +# define pdprintf(s) +#endif + +typedef struct _int_plugin_data_t { + glite_gsplugin_Context ctx; /**< data used for connection etc. */ + int def; /**< is the context created by plugin? */ +} int_plugin_data_t; + +static const char plugin_id[] = PLUGIN_ID; + +static void glite_gsplugin_delete(struct soap *, struct soap_plugin *); +static int glite_gsplugin_copy(struct soap *, struct soap_plugin *, struct soap_plugin *); + +static size_t glite_gsplugin_recv(struct soap *, char *, size_t); +static int glite_gsplugin_send(struct soap *, const char *, size_t); +static int glite_gsplugin_connect(struct soap *, const char *, const char *, int); +static int glite_gsplugin_close(struct soap *); +#if GSOAP_VERSION >= 20700 +static int glite_gsplugin_poll(struct soap *); +#endif +static int glite_gsplugin_accept(struct soap *, int, struct sockaddr *, int *); +static int glite_gsplugin_posthdr(struct soap *soap, const char *key, const char *val); + +static int get_error(int err, edg_wll_GssStatus *gss_stat, const char *msg, char **desc); + +int +glite_gsplugin_init_context(glite_gsplugin_Context *ctx) +{ + glite_gsplugin_Context out = (glite_gsplugin_Context) malloc(sizeof(*out)); + if (!out) return ENOMEM; + + memset(out, 0, sizeof(*out)); + out->cred = NULL; + + /* XXX: some troubles with glite_gss and blocking calls! + out->timeout.tv_sec = 10000; + */ + + out->timeout = NULL; + *ctx = out; + + return 0; +} + +int +glite_gsplugin_free_context(glite_gsplugin_Context ctx) +{ + if (ctx == NULL) + return 0; + + if ( ctx->internal_credentials && ctx->cred != NULL ) + edg_wll_gss_release_cred(&ctx->cred, NULL); + if ( ctx->internal_connection && ctx->connection ) { + if ( ctx->connection->context != NULL ) + edg_wll_gss_close(ctx->connection, NULL); + free(ctx->connection); + } + if (ctx->error_msg) + free(ctx->error_msg); + free(ctx); + + return 0; +} + +glite_gsplugin_Context +glite_gsplugin_get_context(struct soap *soap) +{ + return ((int_plugin_data_t *)soap_lookup_plugin(soap, plugin_id))->ctx; +} + +void * +glite_gsplugin_get_udata(struct soap *soap) +{ + int_plugin_data_t *pdata; + + pdata = (int_plugin_data_t *)soap_lookup_plugin(soap, plugin_id); + assert(pdata); + return pdata->ctx->user_data; +} + +void +glite_gsplugin_set_udata(struct soap *soap, void *d) +{ + int_plugin_data_t *pdata; + + pdata = (int_plugin_data_t *)soap_lookup_plugin(soap, plugin_id); + assert(pdata); + pdata->ctx->user_data = d; +} + +void glite_gsplugin_set_timeout(glite_gsplugin_Context ctx, struct timeval const *to) +{ + if (to) { + ctx->_timeout = *to; + ctx->timeout = &ctx->_timeout; + } + else ctx->timeout = NULL; +} + +int +glite_gsplugin_set_credential(glite_gsplugin_Context ctx, + const char *cert, + const char *key) +{ + edg_wll_GssStatus gss_code; + edg_wll_GssCred cred = NULL; + + int ret; + + ret = edg_wll_gss_acquire_cred_gsi((char *)cert, (char *)key, &cred, &gss_code); + if (ret) + return get_error(ret, &gss_code, "failed to load GSI credentials", &ctx->error_msg); + + if (ctx->internal_credentials && ctx->cred != NULL) + edg_wll_gss_release_cred(&ctx->cred, NULL); + + ctx->cred = cred; + ctx->internal_credentials = 1; + + return 0; +} + +void +glite_gsplugin_use_credential(glite_gsplugin_Context ctx, + edg_wll_GssCred cred) +{ + ctx->cred = cred; + ctx->internal_credentials = 0; +} + +int +glite_gsplugin_set_connection(glite_gsplugin_Context ctx, edg_wll_GssConnection *conn) +{ + int ret = SOAP_OK; + + if ( ctx->connection ) { + if ( ctx->internal_connection && ctx->connection->context != NULL) { + pdprintf(("GSLITE_GSPLUGIN: closing gss connection\n")); + ret = edg_wll_gss_close(ctx->connection, ctx->timeout); + free(ctx->connection); + } + } + ctx->connection = conn; + ctx->internal_connection = 0; + + return ret; +} + +int +glite_gsplugin(struct soap *soap, struct soap_plugin *p, void *arg) +{ + int_plugin_data_t *pdata = (int_plugin_data_t *)malloc(sizeof(int_plugin_data_t)); + + pdprintf(("GSLITE_GSPLUGIN: initializing gSOAP plugin\n")); + if ( !pdata ) return ENOMEM; + if ( arg ) { + pdprintf(("GSLITE_GSPLUGIN: Context is given\n")); + pdata->ctx = (glite_gsplugin_Context)arg; + pdata->def = 0; + } + else { + edg_wll_GssStatus gss_code; + + pdprintf(("GSLITE_GSPLUGIN: Creating default context\n")); + if ( glite_gsplugin_init_context((glite_gsplugin_Context*)&(pdata->ctx)) ) { + free(pdata); + return ENOMEM; + } + if ( edg_wll_gss_acquire_cred_gsi(NULL, NULL, &pdata->ctx->cred, &gss_code) ) { + /* XXX: Let user know, that cred. load failed. Somehow... + */ + glite_gsplugin_free_context(pdata->ctx); + return EINVAL; + } + pdata->ctx->internal_credentials = 1; + pdprintf(("GSLITE_GSPLUGIN: server running with certificate: %s\n", + pdata->ctx->cred->name)); + pdata->def = 1; + } + + p->id = plugin_id; + p->data = pdata; + p->fdelete = glite_gsplugin_delete; + p->fcopy = glite_gsplugin_copy; + + soap->fopen = glite_gsplugin_connect; + soap->fconnect = NULL; + soap->fclose = glite_gsplugin_close; +#if GSOAP_VERSION >= 20700 + soap->fpoll = glite_gsplugin_poll; +#endif + soap->faccept = glite_gsplugin_accept; + soap->fsend = glite_gsplugin_send; + soap->frecv = glite_gsplugin_recv; + soap->fposthdr = glite_gsplugin_posthdr; + + return SOAP_OK; +} + + +char *glite_gsplugin_errdesc(struct soap *soap) +{ + glite_gsplugin_Context ctx; + + ctx = ((int_plugin_data_t *)soap_lookup_plugin(soap, plugin_id))->ctx; + if ( ctx ) return ctx->error_msg; + + return NULL; +} + + + +static int +glite_gsplugin_copy(struct soap *soap, struct soap_plugin *dst, struct soap_plugin *src) +{ + pdprintf(("GSLITE_GSPLUGIN: glite_gsplugin_copy()\n")); + /* Should be the copy code here? + */ + return ENOSYS; +} + +static void +glite_gsplugin_delete(struct soap *soap, struct soap_plugin *p) +{ + int_plugin_data_t *d = (int_plugin_data_t *)soap_lookup_plugin(soap, plugin_id); + + pdprintf(("GSLITE_GSPLUGIN: glite_gsplugin_delete()\n")); + if ( d->def ) { + glite_gsplugin_close(soap); + glite_gsplugin_free_context(d->ctx); + } + free(d); +} + + +static int +glite_gsplugin_connect( + struct soap *soap, + const char *endpoint, + const char *host, + int port) +{ + glite_gsplugin_Context ctx; + edg_wll_GssStatus gss_stat; + int ret; + const char *msg = NULL; + + + pdprintf(("GSLITE_GSPLUGIN: glite_gsplugin_connect()\n")); +#if defined(CHECK_GSOAP_VERSION) && GSOAP_VERSION <= 20700 + if ( GSOAP_VERSION < 20700 + || (GSOAP_VERSION == 20700 + && (strlen(GSOAP_MIN_VERSION) < 1 || GSOAP_MIN_VERSION[1] < 'e')) ) { + fprintf(stderr, "Client connect will work only with gSOAP v2.7.0e and later"); + soap->errnum = ENOSYS; + return ENOSYS; + } +#endif + + ctx = ((int_plugin_data_t *)soap_lookup_plugin(soap, plugin_id))->ctx; + if (ctx->connection) { + pdprintf(("GSLITE_GSPLUGIN: Warning: connection dropped, new to %s:%d\n", host, port)); + } + pdprintf(("GSLITE_GSPLUGIN: connection to %s:%d will be established\n", host, port)); + + if ( ctx->cred == NULL ) { + pdprintf(("GSLITE_GSPLUGIN: loading default credentials\n")); + ret = edg_wll_gss_acquire_cred_gsi(NULL, NULL, + &ctx->cred, &gss_stat); + if ( ret ) { + msg = "failed to load GSI credentials"; + goto err; + } + ctx->internal_credentials = 1; + } + + if ( !(ctx->connection = (edg_wll_GssConnection *)malloc(sizeof(*ctx->connection))) ) return errno; + ret = edg_wll_gss_connect(ctx->cred, + host, port, + ctx->timeout, + ctx->connection, &gss_stat); + if ( ret ) { + free(ctx->connection); + ctx->connection = NULL; + msg = "edg_wll_gss_connect() error"; + goto err; + } + ctx->internal_connection = 1; + + soap->errnum = 0; + return ctx->connection->sock; + +err: + pdprintf(("GSLITE_GSPLUGIN: glite_gsplugin_connect() error!\n")); + + soap->errnum = get_error(ret, &gss_stat, msg, &ctx->error_msg); + + switch ( ret ) { + case EDG_WLL_GSS_ERROR_GSS: + soap_set_sender_error(soap, "SSL error", "SSL authentication failed in tcp_connect(): check password, key file, and ca file.", SOAP_SSL_ERROR); + break; + case EDG_WLL_GSS_ERROR_HERRNO: + soap_set_sender_error(soap, "connection error", hstrerror(soap->errnum), SOAP_CLI_FAULT); + break; + case EDG_WLL_GSS_ERROR_EOF: + soap->errnum = ECONNREFUSED; + soap_set_sender_error(soap, "connection error", strerror(soap->errnum), SOAP_CLI_FAULT); + break; + case EDG_WLL_GSS_ERROR_ERRNO: + case EDG_WLL_GSS_ERROR_TIMEOUT: + soap_set_sender_error(soap, "connection error", strerror(soap->errnum), SOAP_CLI_FAULT); + break; + default: + soap_set_sender_error(soap, "unknown error", "", SOAP_CLI_FAULT); + break; + } + + return SOAP_INVALID_SOCKET; +} + +/** It is called in soap_closesocket() + * + * return like errno value + */ +static int +glite_gsplugin_close(struct soap *soap) +{ + glite_gsplugin_Context ctx; + + pdprintf(("GSLITE_GSPLUGIN: glite_gsplugin_close()\n")); + ctx = ((int_plugin_data_t *)soap_lookup_plugin(soap, plugin_id))->ctx; + return glite_gsplugin_set_connection(ctx, NULL); +} + + +static int +glite_gsplugin_accept(struct soap *soap, int s, struct sockaddr *a, int *n) +{ + glite_gsplugin_Context ctx; + edg_wll_GssStatus gss_code; + int conn; + int ret; + + soap->errnum = 0; + pdprintf(("GSLITE_GSPLUGIN: glite_gsplugin_accept()\n")); + ctx = ((int_plugin_data_t *)soap_lookup_plugin(soap, plugin_id))->ctx; + if ( (conn = accept(s, (struct sockaddr *)&a, (socklen_t *)n)) < 0 ) return conn; + if ( !ctx->connection ) { + if ( !(ctx->connection = (edg_wll_GssConnection *)malloc(sizeof(*ctx->connection))) ) { + close(conn); + soap_set_receiver_error(soap, "malloc error", strerror(ENOMEM), ENOMEM); + return SOAP_INVALID_SOCKET; + } + ctx->internal_connection = 1; + } + if ( (ret = edg_wll_gss_accept(ctx->cred, conn, ctx->timeout, ctx->connection, &gss_code)) != 0) { + pdprintf(("GSLITE_GSPLUGIN: Client authentication failed, closing.\n")); + close(conn); + get_error(ret, &gss_code, "Client authentication failed", &ctx->error_msg); + soap->errnum = SOAP_SVR_FAULT; + soap_set_receiver_error(soap, "SSL error", "SSL authentication failed in tcp_connect(): check password, key file, and ca file.", SOAP_SSL_ERROR); + return SOAP_INVALID_SOCKET; + } + + return conn; +} + +static size_t +glite_gsplugin_recv(struct soap *soap, char *buf, size_t bufsz) +{ + glite_gsplugin_Context ctx; + edg_wll_GssStatus gss_code; + int len; + + + ctx = ((int_plugin_data_t *)soap_lookup_plugin(soap, plugin_id))->ctx; + if ( ctx->error_msg ) { free(ctx->error_msg); ctx->error_msg = NULL; } + + if ( ctx->connection->context == NULL ) { + soap->errnum = ENOTCONN; + /* XXX: glite_gsplugin_send() returns SOAP_EOF on errors + */ + return 0; + } + + len = edg_wll_gss_read(ctx->connection, buf, bufsz, + ctx->timeout, + &gss_code); + + switch ( len ) { + case EDG_WLL_GSS_OK: + break; + case EDG_WLL_GSS_ERROR_GSS: + case EDG_WLL_GSS_ERROR_ERRNO: + case EDG_WLL_GSS_ERROR_TIMEOUT: + case EDG_WLL_GSS_ERROR_EOF: + soap->errnum = get_error(len, &gss_code, "receiving WS request", &ctx->error_msg); + return 0; + /* default: fallthrough */ + } + pdprintf(("GSLITE_GSPLUGIN: glite_gsplugin_recv() = %d\n",len)); + + return len; +} + +static int +glite_gsplugin_send(struct soap *soap, const char *buf, size_t bufsz) +{ + glite_gsplugin_Context ctx; + edg_wll_GssStatus gss_code; + struct sigaction sa, osa; + size_t total = 0; + int ret; + + + ctx = ((int_plugin_data_t *)soap_lookup_plugin(soap, plugin_id))->ctx; + /* XXX: check whether ctx is initialized + * i.e. ctx->connection != NULL + */ + if ( ctx->error_msg ) { free(ctx->error_msg); ctx->error_msg = NULL; } + if ( ctx->connection == NULL || ctx->connection->context == NULL ) { + soap->errnum = ENOTCONN; + return SOAP_EOF; + } + + memset(&sa, 0, sizeof(sa)); + assert(sa.sa_handler == NULL); + sa.sa_handler = SIG_IGN; + sigaction(SIGPIPE, &sa, &osa); + + ret = edg_wll_gss_write_full(ctx->connection, + (void*)buf, bufsz, ctx->timeout, &total, &gss_code); + + sigaction(SIGPIPE, &osa, NULL); + + pdprintf(("GSLITE_GSPLUGIN: glite_gsplugin_send(%d) = %d\n",bufsz,ret)); + + soap->errnum = get_error(ret, &gss_code, "sending WS request", &ctx->error_msg); + + switch ( ret ) { + case EDG_WLL_GSS_OK: + return SOAP_OK; + + case EDG_WLL_GSS_ERROR_ERRNO: + if (soap->errnum == EPIPE) soap->errnum = ENOTCONN; + return SOAP_EOF; + + case EDG_WLL_GSS_ERROR_TIMEOUT: + case EDG_WLL_GSS_ERROR_GSS: + case EDG_WLL_GSS_ERROR_EOF: + default: + return SOAP_EOF; + } +} + + +#if GSOAP_VERSION >= 20700 +static int +glite_gsplugin_poll(struct soap *soap) +{ + glite_gsplugin_Context ctx; + fd_set readfds; + struct timeval timeout = {tv_sec: 0, tv_usec: 0}; + int ret; + + ctx = ((int_plugin_data_t *)soap_lookup_plugin(soap, plugin_id))->ctx; + if (!ctx->connection || !ctx->connection->context) { + pdprintf(("GSLITE_GSPLUGIN: glite_gsplugin_poll, no connection\n")); + return SOAP_EOF; + } + + FD_ZERO(&readfds); + FD_SET(ctx->connection->sock, &readfds); + ret = select(ctx->connection->sock + 1, &readfds, NULL, NULL, &timeout); + if (ret < 0) { + pdprintf(("GSLITE_GSPLUGIN: glite_gsplugin_poll, select(%d) failed\n", ctx->connection->sock)); + return SOAP_TCP_ERROR; + } else if (ret == 0) { + /* has been OK but server can disconnect anytime */ + return SOAP_OK; + } else { + pdprintf(("GSLITE_GSPLUGIN: glite_gsplugin_poll, select(%d) = %d\n", ctx->connection->sock, ret)); + return SOAP_EOF; + } +} +#endif + + +static int http_send_header(struct soap *soap, const char *s) { + const char *t; + + do { + t = strchr(s, '\n'); /* disallow \n in HTTP headers */ + if (!t) t = s + strlen(s); + if (soap_send_raw(soap, s, t - s)) return soap->error; + s = t + 1; + } while (*t); + + return SOAP_OK; +} + + +static int glite_gsplugin_posthdr(struct soap *soap, const char *key, const char *val) { + if (key) { + if (strcmp(key, "Status") == 0) { + snprintf(soap->tmpbuf, sizeof(soap->tmpbuf), "HTTP/%s", soap->http_version); + if (http_send_header(soap, soap->tmpbuf)) return soap->error; + if (val && (soap_send_raw(soap, " ", 1) || http_send_header(soap, val))) + return soap->error; + } else { + if (http_send_header(soap, key)) return soap->error; + if (val && (soap_send_raw(soap, ": ", 2) || http_send_header(soap, val))) + return soap->error; + } + } + + return soap_send_raw(soap, "\r\n", 2); +} + + +static int get_error(int err, edg_wll_GssStatus *gss_stat, const char *msg, char **desc) { + int num; + const char *s; + + if (desc) { + free(*desc); + *desc = NULL; + } + + switch (err) { + case EDG_WLL_GSS_OK: + return 0; + case EDG_WLL_GSS_ERROR_GSS: + if (desc) edg_wll_gss_get_error(gss_stat, msg, desc); + return ENOTCONN; + case EDG_WLL_GSS_ERROR_HERRNO: + num = h_errno; + s = hstrerror(num); + if (desc) { + if (s) asprintf(desc, "%s: %s", msg, s); + else asprintf(desc, "%s: herrno %d", msg, num); + } + return num; + case EDG_WLL_GSS_ERROR_ERRNO: + num = errno; + break; + case EDG_WLL_GSS_ERROR_TIMEOUT: + num = ETIMEDOUT; + break; + case EDG_WLL_GSS_ERROR_EOF: + num = ENOTCONN; + break; + default: + if (desc) asprintf(desc, "%s: unknown error type %d from glite_gss", msg, err); + return EINVAL; + } + + if (desc) asprintf(desc, "%s: %s", msg, strerror(num)); + return num; +} diff --git a/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.6.2.c b/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.6.2.c new file mode 100644 index 0000000..78c4872 --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.6.2.c @@ -0,0 +1,11020 @@ +/* + +stdsoap2.c[pp] 2.6.2 + +Runtime environment. + +gSOAP XML Web services tools +Copyright (C) 2000-2004, Robert van Engelen, Genivia, Inc. All Rights Reserved. + +Contributors: + +Wind River Systems, Inc., for the following additions (marked WR[...]): + - vxWorks compatible + - Support for IPv6. + +-------------------------------------------------------------------------------- +gSOAP public license. + +The contents of this file are subject to the gSOAP Public License Version 1.3 +(the "License"); you may not use this file except in compliance with the +License. You may obtain a copy of the License at +http://www.cs.fsu.edu/~engelen/soaplicense.html +Software distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +for the specific language governing rights and limitations under the License. + +The Initial Developer of the Original Code is Robert A. van Engelen. +Copyright (C) 2000-2004 Robert A. van Engelen, Genivia inc. All Rights Reserved. +-------------------------------------------------------------------------------- +GPL license. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA + +Author contact information: +engelen@genivia.com / engelen@acm.org +-------------------------------------------------------------------------------- + +Installation note: + +Win32 build needs winsock.dll (Visual C++ "wsock32.lib") +To do this in Visual C++ 6.0, go to "Project", "settings", select the "Link" +tab (the project file needs to be selected in the file view) and add +"wsock32.lib" to the "Object/library modules" entry + +*/ + +#include "stdsoap2.h" + +#ifdef __cplusplus +SOAP_SOURCE_STAMP("@(#) stdsoap2.cpp ver 2.6.2 2004-06-12 12:00:00 GMT") +extern "C" { +#else +SOAP_SOURCE_STAMP("@(#) stdsoap2.c ver 2.6.2 2004-06-12 12:00:00 GMT") +#endif + +/* 8bit character representing unknown/nonrepresentable character data (not supported by current locale) */ +#ifndef SOAP_UNKNOWN_CHAR +#define SOAP_UNKNOWN_CHAR (127) +#endif + +/* EOF=-1 */ +#define LT (wchar)(-2) /* XML character '<' */ +#define TT (wchar)(-3) /* XML character '' */ +#define QT (wchar)(-5) /* XML character '"' */ +#define AP (wchar)(-6) /* XML character ''' */ + +#define soap_blank(c) ((c) >= 0 && (c) <= 32) +#define soap_notblank(c) ((c) > 32) +#define soap_hash_ptr(p) (((unsigned long)(p) >> 3) & (SOAP_PTRHASH - 1)) + +static int soap_isxdigit(int); +static wchar soap_char(struct soap*); +static wchar soap_getchunkchar(struct soap*); +static void soap_update_ptrs(struct soap*, char*, char*, long); +static int soap_has_copies(struct soap*, char*, char*); +static struct soap_ilist *soap_hlookup(struct soap*, const char*); +static void soap_init_iht(struct soap*); +static void soap_free_iht(struct soap*); +static void soap_init_pht(struct soap*); +static void soap_free_pht(struct soap*); +static int soap_set_error(struct soap*, const char*, const char*, const char*, int); +static int soap_copy_fault(struct soap*, const char*, const char*, const char*); +static int soap_getattrval(struct soap*, char*, size_t, wchar); +static void soap_set_local_namespaces(struct soap*); +static size_t soap_begin_dime(struct soap*); +static int soap_isnumeric(struct soap*, const char*); +static void *fplugin(struct soap*, const char*); + +#ifndef WITH_LEAN +static time_t soap_timegm(struct tm*); +static void soap_init_logs(struct soap*); +static void soap_close_logfile(struct soap*, int); +static void soap_set_logfile(struct soap*, int, const char*); +#endif + +#ifdef WITH_FAST +/* Use look-aside buffers */ +static int soap_append_lab(struct soap*, const char*, size_t); +#endif + +#ifndef WITH_LEANER +static int soap_putdimefield(struct soap*, const char*, size_t); +static char *soap_getdimefield(struct soap*, size_t); +#endif + +#ifdef WITH_GZIP +static int soap_getgzipheader(struct soap*); +#endif + +#ifdef WITH_OPENSSL +static int ssl_auth_init(struct soap*); +static int ssl_verify_callback(int, X509_STORE_CTX*); +static int ssl_password(char*, int, int, void *); +/* This callback is included for future references. It should not be deleted +static DH *ssl_tmp_dh(SSL*, int, int); +*/ +#endif + +static const char *soap_strerror(struct soap*); +static const char *tcp_error(struct soap*); +static const char *http_error(struct soap*, int); +static int http_post(struct soap*, const char*, const char*, int, const char*, const char*, size_t); +static int http_get(struct soap*); +static int http_post_header(struct soap*, const char*, const char*); +static int http_response(struct soap*, int, size_t); +static int http_parse(struct soap*); +static int http_parse_header(struct soap*, const char*, const char*); +static int tcp_connect(struct soap*, const char*, const char*, int); +static int tcp_accept(struct soap*, int, struct sockaddr*, int*); +static int tcp_disconnect(struct soap*); +static int fsend(struct soap*, const char*, size_t); +static size_t frecv(struct soap*, char*, size_t); + +/* WR[ */ +#ifdef VXWORKS +static int vx_nonblocking = TRUE; /* ioctl argument */ +#endif +/* ]WR */ + +#ifndef PALM_2 +static const char soap_env1[42] = "http://schemas.xmlsoap.org/soap/envelope/"; +static const char soap_enc1[42] = "http://schemas.xmlsoap.org/soap/encoding/"; +static const char soap_env2[40] = "http://www.w3.org/2003/05/soap-envelope"; +static const char soap_enc2[40] = "http://www.w3.org/2003/05/soap-encoding"; +static const char soap_rpc[35] = "http://www.w3.org/2003/05/soap-rpc"; +#endif + +#ifndef PALM_1 +const struct soap_double_nan soap_double_nan = {0xFFFFFFFF, 0xFFFFFFFF}; +static const char soap_base64o[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char soap_base64i[81] = "\76XXX\77\64\65\66\67\70\71\72\73\74\75XXXXXXX\00\01\02\03\04\05\06\07\10\11\12\13\14\15\16\17\20\21\22\23\24\25\26\27\30\31XXXXXX\32\33\34\35\36\37\40\41\42\43\44\45\46\47\50\51\52\53\54\55\56\57\60\61\62\63"; +#endif + +static const char soap_padding[3] = "\0\0"; +#define SOAP_STR_PADDING (soap_padding) +#define SOAP_STR_EOS (soap_padding) + +#ifndef WITH_LEAN +static const struct soap_code_map html_entity_codes[] = /* entities for XHTML parsing */ +{ { 160, "nbsp" }, + { 161, "iexcl" }, + { 162, "cent" }, + { 163, "pound" }, + { 164, "curren" }, + { 165, "yen" }, + { 166, "brvbar" }, + { 167, "sect" }, + { 168, "uml" }, + { 169, "copy" }, + { 170, "ordf" }, + { 171, "laquo" }, + { 172, "not" }, + { 173, "shy" }, + { 174, "reg" }, + { 175, "macr" }, + { 176, "deg" }, + { 177, "plusmn" }, + { 178, "sup2" }, + { 179, "sup3" }, + { 180, "acute" }, + { 181, "micro" }, + { 182, "para" }, + { 183, "middot" }, + { 184, "cedil" }, + { 185, "sup1" }, + { 186, "ordm" }, + { 187, "raquo" }, + { 188, "frac14" }, + { 189, "frac12" }, + { 190, "frac34" }, + { 191, "iquest" }, + { 192, "Agrave" }, + { 193, "Aacute" }, + { 194, "Acirc" }, + { 195, "Atilde" }, + { 196, "Auml" }, + { 197, "Aring" }, + { 198, "AElig" }, + { 199, "Ccedil" }, + { 200, "Egrave" }, + { 201, "Eacute" }, + { 202, "Ecirc" }, + { 203, "Euml" }, + { 204, "Igrave" }, + { 205, "Iacute" }, + { 206, "Icirc" }, + { 207, "Iuml" }, + { 208, "ETH" }, + { 209, "Ntilde" }, + { 210, "Ograve" }, + { 211, "Oacute" }, + { 212, "Ocirc" }, + { 213, "Otilde" }, + { 214, "Ouml" }, + { 215, "times" }, + { 216, "Oslash" }, + { 217, "Ugrave" }, + { 218, "Uacute" }, + { 219, "Ucirc" }, + { 220, "Uuml" }, + { 221, "Yacute" }, + { 222, "THORN" }, + { 223, "szlig" }, + { 224, "agrave" }, + { 225, "aacute" }, + { 226, "acirc" }, + { 227, "atilde" }, + { 228, "auml" }, + { 229, "aring" }, + { 230, "aelig" }, + { 231, "ccedil" }, + { 232, "egrave" }, + { 233, "eacute" }, + { 234, "ecirc" }, + { 235, "euml" }, + { 236, "igrave" }, + { 237, "iacute" }, + { 238, "icirc" }, + { 239, "iuml" }, + { 240, "eth" }, + { 241, "ntilde" }, + { 242, "ograve" }, + { 243, "oacute" }, + { 244, "ocirc" }, + { 245, "otilde" }, + { 246, "ouml" }, + { 247, "divide" }, + { 248, "oslash" }, + { 249, "ugrave" }, + { 250, "uacute" }, + { 251, "ucirc" }, + { 252, "uuml" }, + { 253, "yacute" }, + { 254, "thorn" }, + { 255, "yuml" }, + { 0, NULL } +}; +#endif + +#ifndef WITH_LEAN +static const struct soap_code_map h_error_codes[] = +{ +#ifdef HOST_NOT_FOUND + { HOST_NOT_FOUND, "Host not found" }, +#endif +#ifdef TRY_AGAIN + { TRY_AGAIN, "Try Again" }, +#endif +#ifdef NO_RECOVERY + { NO_RECOVERY, "No Recovery" }, +#endif +#ifdef NO_DATA + { NO_DATA, "No Data" }, +#endif +#ifdef NO_ADDRESS + { NO_ADDRESS, "No Address" }, +#endif + { 0, NULL } +}; +#endif + +#ifndef WITH_LEAN +static const struct soap_code_map h_http_error_codes[] = +{ { 201, "Created" }, + { 202, "Accepted" }, + { 203, "Non-Authoritative Information" }, + { 204, "No Content" }, + { 205, "Reset Content" }, + { 206, "Partial Content" }, + { 300, "Multiple Choices" }, + { 301, "Moved Permanently" }, + { 302, "Found" }, + { 303, "See Other" }, + { 304, "Not Modified" }, + { 305, "Use Proxy" }, + { 307, "Temporary Redirect" }, + { 400, "Bad Request" }, + { 401, "Unauthorized" }, + { 402, "Payment Required" }, + { 403, "Forbidden" }, + { 404, "Not Found" }, + { 405, "Method Not Allowed" }, + { 406, "Not Acceptable" }, + { 407, "Proxy Authentication Required" }, + { 408, "Request Time-out" }, + { 409, "Conflict" }, + { 410, "Gone" }, + { 411, "Length Required" }, + { 412, "Precondition Failed" }, + { 413, "Request Entity Too Large" }, + { 414, "Request-URI Too Large" }, + { 415, "Unsupported Media Type" }, + { 416, "Requested range not satisfiable" }, + { 417, "Expectation Failed" }, + { 500, "Internal Server Error" }, + { 501, "Not Implemented" }, + { 502, "Bad Gateway" }, + { 503, "Service Unavailable" }, + { 504, "Gateway Time-out" }, + { 505, "HTTP Version not supported" }, + { 0, NULL } +}; +#endif + +#ifdef WITH_OPENSSL +static const struct soap_code_map h_ssl_error_codes[] = +{ +#define _SSL_ERROR(e) { e, #e } + _SSL_ERROR(SSL_ERROR_SSL), + _SSL_ERROR(SSL_ERROR_ZERO_RETURN), + _SSL_ERROR(SSL_ERROR_WANT_READ), + _SSL_ERROR(SSL_ERROR_WANT_WRITE), + _SSL_ERROR(SSL_ERROR_WANT_CONNECT), + _SSL_ERROR(SSL_ERROR_WANT_X509_LOOKUP), + _SSL_ERROR(SSL_ERROR_SYSCALL), + { 0, NULL } +}; +#endif + +#ifdef WIN32 +static int tcp_done = 0; +#endif + +/******************************************************************************/ +#ifndef MAC_CARBON +#ifndef PALM_1 +static int +fsend(struct soap *soap, const char *s, size_t n) +{ register int nwritten; +#if defined(__cplusplus) && !defined(UNDER_CE) + if (soap->os) + { soap->os->write(s, n); + if (soap->os->good()) + return SOAP_OK; + return SOAP_EOF; + } +#endif + while (n) + { if (soap_valid_socket(soap->socket)) + { +#ifndef WITH_LEAN + if (soap->send_timeout) + { struct timeval timeout; + fd_set fd; + if (soap->send_timeout > 0) + { timeout.tv_sec = soap->send_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->send_timeout/1000000; + timeout.tv_usec = -soap->send_timeout%1000000; + } + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->socket, &fd); + for (;;) + { register int r = select((SOAP_SOCKET)(soap->socket + 1), NULL, &fd, &fd, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + return SOAP_EOF; + } + if (soap_socket_errno != SOAP_EINTR) + { soap->errnum = soap_socket_errno; + return SOAP_EOF; + } + } + } +#endif +#ifdef WITH_OPENSSL + if (soap->ssl) + nwritten = SSL_write(soap->ssl, s, n); + else +#endif +#ifndef PALM + nwritten = send((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags); +#else + nwritten = send((SOAP_SOCKET)soap->socket, (void*)s, n, soap->socket_flags); +#endif + if (nwritten <= 0) + { +#ifdef WITH_OPENSSL + int err; + if (soap->ssl && (err = SSL_get_error(soap->ssl, nwritten)) != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) + return SOAP_EOF; +#endif + if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EWOULDBLOCK && soap_socket_errno != SOAP_EAGAIN) + { soap->errnum = soap_socket_errno; + return SOAP_EOF; + } + nwritten = 0; /* and call write() again */ + } + } + else + { +#ifdef WITH_FASTCGI + nwritten = fwrite((void*)s, 1, n, stdout); + fflush(stdout); +#else +#ifdef UNDER_CE + nwritten = fwrite(s, 1, n, soap->sendfd); +#else +/* WR[ */ +#ifdef VXWORKS +#ifdef WMW_RPM_IO + if (soap->rpmreqid) + { + httpBlockPut(soap->rpmreqid, s, n); + nwritten = n; + } + else + { + nwritten = fwrite(s, sizeof(char), n, fdopen(soap->sendfd, "w")); + } +#else + nwritten = fwrite(s, sizeof(char), n, fdopen(soap->sendfd, "w")); +#endif /* WMW_RPM_IO */ +#else +/* ]WR */ + nwritten = write((SOAP_SOCKET)soap->sendfd, s, n); +/* WR[ */ +#endif +/* ]WR */ +#endif +#endif + if (nwritten <= 0) + { if (soap_errno != SOAP_EINTR && soap_errno != SOAP_EWOULDBLOCK && soap_errno != SOAP_EAGAIN) + { soap->errnum = soap_errno; + return SOAP_EOF; + } + nwritten = 0; /* and call write() again */ + } + } + n -= nwritten; + s += nwritten; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_flush_raw(struct soap *soap, const char *s, size_t n) +{ +#ifndef WITH_LEAN + if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) + { char *t; + if (!(t = (char*)soap_push_block(soap, n))) + return soap->error = SOAP_EOM; + memcpy(t, s, n); + return SOAP_OK; + } + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) + { char t[16]; + sprintf(t, "\r\n%lX\r\n" + (soap->chunksize ? 0 : 2), (unsigned long)n); + DBGMSG(SENT, t, strlen(t)); + if ((soap->error = soap->fsend(soap, t, strlen(t)))) + return soap->error; + soap->chunksize += n; + } +#endif + DBGMSG(SENT, s, n); + return soap->error = soap->fsend(soap, s, n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_flush(struct soap *soap) +{ if (soap->bufidx) + { +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { soap->d_stream.next_in = (Byte*)soap->buf; + soap->d_stream.avail_in = (unsigned int)soap->bufidx; +#ifdef WITH_GZIP + soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->bufidx); +#endif + do + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating %u bytes\n", soap->d_stream.avail_in)); + if (deflate(&soap->d_stream, Z_NO_FLUSH) != Z_OK) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to deflate: %s\n", soap->d_stream.msg?soap->d_stream.msg:"")); + return soap->error = SOAP_ZLIB_ERROR; + } + if (!soap->d_stream.avail_out) + { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN)) + return soap->error; + soap->d_stream.next_out = (Byte*)soap->z_buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + } + } while (soap->d_stream.avail_in); + } + else +#endif + if (soap_flush_raw(soap, soap->buf, soap->bufidx)) + return soap->error; + soap->bufidx = 0; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send_raw(struct soap *soap, const char *s, size_t n) +{ if (!n) + return SOAP_OK; + if (soap->mode & SOAP_IO_LENGTH) + { soap->count += n; + if (soap->fprepare) + return soap->fprepare(soap, s, n); + return SOAP_OK; + } + if (soap->mode & SOAP_IO) + { register size_t i = SOAP_BUFLEN - soap->bufidx; + while (n >= i) + { memcpy(soap->buf + soap->bufidx, s, i); + soap->bufidx = SOAP_BUFLEN; + if (soap_flush(soap)) + return soap->error; + s += i; + n -= i; + i = SOAP_BUFLEN; + } + memcpy(soap->buf + soap->bufidx, s, n); + soap->bufidx += n; + return SOAP_OK; + } + return soap_flush_raw(soap, s, n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send(struct soap *soap, const char *s) +{ if (s) + return soap_send_raw(soap, s, strlen(s)); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef MAC_CARBON +#ifndef PALM_1 +static size_t +frecv(struct soap *soap, char *s, size_t n) +{ register int r; + soap->errnum = 0; +#if defined(__cplusplus) && !defined(UNDER_CE) + if (soap->is) + { if (soap->is->good()) + return soap->is->read(s, n).gcount(); + return 0; + } +#endif + if (soap_valid_socket(soap->socket)) + { for (;;) + { +#ifndef WITH_LEAN + struct timeval timeout; + fd_set fd; + if (soap->recv_timeout) + { if (soap->recv_timeout > 0) + { timeout.tv_sec = soap->recv_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->recv_timeout/1000000; + timeout.tv_usec = -soap->recv_timeout%1000000; + } + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->socket, &fd); + for (;;) + { r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout); + if (r > 0) + break; + if (r == 0) + return 0; + if (soap_socket_errno != SOAP_EINTR) + { soap->errnum = soap_socket_errno; + return 0; + } + } + } +#endif +#ifdef WITH_OPENSSL + if (soap->ssl) + { int err; + r = SSL_read(soap->ssl, s, n); + if ((err = SSL_get_error(soap->ssl, r)) == SSL_ERROR_NONE) + return (size_t)r; + if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) + return 0; + } + else +#endif + { r = recv((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags); + if (r >= 0) + return (size_t)r; + if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EAGAIN) + { soap->errnum = soap_socket_errno; + return 0; + } + } +#ifndef WITH_LEAN + { struct timeval timeout; + fd_set fd; + timeout.tv_sec = 0; + timeout.tv_usec = 10000; + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->socket, &fd); + r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout); + if (r < 0 && soap_socket_errno != SOAP_EINTR) + { soap->errnum = soap_socket_errno; + return 0; + } + } +#endif + } + } +#ifdef WITH_FASTCGI + return fread(s, 1, n, stdin); +#else +#ifdef UNDER_CE + return fread(s, 1, n, soap->recvfd); +#else +/* WR[ */ +#ifdef WMW_RPM_IO + if (soap->rpmreqid) + { + r = httpBlockRead(soap->rpmreqid, s, n); + } + else + { + r = read(soap->recvfd, s, n); + } + if (r >= 0) + { + return r; + } + return 0; +#else +/* ]WR */ + r = read((SOAP_SOCKET)soap->recvfd, s, n); + if (r >= 0) + return (size_t)r; + soap->errnum = soap_errno; + return 0; +/* WR[ */ +#endif +/* ]WR */ +#endif +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static wchar +soap_getchunkchar(struct soap *soap) +{ if (soap->bufidx < soap->buflen) + return soap->buf[soap->bufidx++]; + soap->bufidx = 0; + soap->buflen = soap->chunkbuflen = soap->frecv(soap, soap->buf, SOAP_BUFLEN); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes\n", (unsigned int)soap->buflen)); + DBGMSG(RECV, soap->buf, soap->buflen); + if (soap->buflen) + return soap->buf[soap->bufidx++]; + return EOF; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +soap_isxdigit(int c) +{ switch (c) + { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + return 1; + } + return 0; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv_raw(struct soap *soap) +{ register size_t ret; +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { if (soap->d_stream.next_out == Z_NULL) + return EOF; + if (soap->d_stream.avail_in || !soap->d_stream.avail_out) + { register int r; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflating\n")); + soap->d_stream.next_out = (Byte*)soap->buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + r = inflate(&soap->d_stream, Z_NO_FLUSH); + if (r == Z_OK || r == Z_STREAM_END) + { soap->bufidx = 0; + soap->buflen = SOAP_BUFLEN - soap->d_stream.avail_out; + if (soap->zlib_in == SOAP_ZLIB_GZIP) + soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen); + if (r == Z_STREAM_END) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out)); + soap->z_ratio_in = (float)soap->d_stream.total_in / (float)soap->d_stream.total_out; + soap->d_stream.next_out = Z_NULL; + } + if (soap->buflen) + { soap->count += soap->buflen; + return SOAP_OK; + } + } + else if (r != Z_BUF_ERROR) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate error: %s\n", soap->d_stream.msg?soap->d_stream.msg:"")); + soap->d_stream.next_out = Z_NULL; + return EOF; + } + } +zlib_again: + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK && !soap->chunksize) + { memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN); + soap->buflen = soap->z_buflen; + } + } +#endif + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) /* read HTTP chunked transfer */ + { +chunk_again: + if (soap->chunksize) + { soap->buflen = ret = soap->frecv(soap, soap->buf, soap->chunksize > SOAP_BUFLEN ? SOAP_BUFLEN : soap->chunksize); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk: read %u bytes\n", (unsigned int)ret)); + DBGMSG(RECV, soap->buf, ret); + soap->bufidx = 0; + soap->chunksize -= ret; + } + else + { register wchar c; + char tmp[8], *t; + t = tmp; + if (!soap->chunkbuflen) + { soap->chunkbuflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes\n", (unsigned int)ret)); + DBGMSG(RECV, soap->buf, ret); + soap->bufidx = 0; + if (!ret) + return EOF; + } + else + soap->bufidx = soap->buflen; + soap->buflen = soap->chunkbuflen; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk size (%u %u)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen)); + while (!soap_isxdigit((int)(c = soap_getchunkchar(soap)))) + if ((int)c == EOF) + return EOF; + do + *t++ = (char)c; + while (soap_isxdigit((int)(c = soap_getchunkchar(soap))) && t - tmp < 7); + while ((int)c != EOF && c != '\n') + c = soap_getchunkchar(soap); + if ((int)c == EOF) + return EOF; + *t = '\0'; + soap->chunksize = soap_strtoul(tmp, &t, 16); + if (!soap->chunksize) + { soap->chunkbuflen = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of chunked message\n")); + while ((int)c != EOF && c != '\n') + c = soap_getchunkchar(soap); + return EOF; + } + soap->buflen = soap->bufidx + soap->chunksize; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving buf len to %u (%u %s)\n", (unsigned int)soap->buflen, (unsigned int)soap->bufidx, tmp)); + if (soap->buflen > soap->chunkbuflen) + { soap->buflen = soap->chunkbuflen; + soap->chunksize -= soap->buflen - soap->bufidx; + soap->chunkbuflen = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Passed end of buffer for chunked HTTP (%lu bytes left)\n", (unsigned long)(soap->buflen - soap->bufidx))); + } + else if (soap->chunkbuflen) + soap->chunksize = 0; + ret = soap->buflen - soap->bufidx; + if (!ret) + goto chunk_again; + } + } + else + { soap->bufidx = 0; + soap->buflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes\n", (unsigned int)ret)); + DBGMSG(RECV, soap->buf, ret); + } +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { int r; + memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); + soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx); + soap->d_stream.avail_in = (unsigned int)ret; + soap->d_stream.next_out = (Byte*)soap->buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + r = inflate(&soap->d_stream, Z_NO_FLUSH); + if (r == Z_OK || r == Z_STREAM_END) + { soap->bufidx = 0; + soap->z_buflen = soap->buflen; + soap->buflen = ret = SOAP_BUFLEN - soap->d_stream.avail_out; + if (soap->zlib_in == SOAP_ZLIB_GZIP) + soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %u bytes\n", (unsigned int)ret)); + if (!ret) + goto zlib_again; + if (r == Z_STREAM_END) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out)); + soap->z_ratio_in = (float)soap->d_stream.total_in / (float)soap->d_stream.total_out; + soap->d_stream.next_out = Z_NULL; + } + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to inflate: (%d) %s\n", r, soap->d_stream.msg?soap->d_stream.msg:"")); + soap->d_stream.next_out = Z_NULL; + return EOF; + } + } +#endif + soap->count += ret; + return !ret; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv(struct soap *soap) +{ +#ifndef WITH_LEANER + if (soap->mode & SOAP_ENC_DIME) + { if (soap->dime_buflen) + { char *s; + int i; + unsigned char tmp[12]; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME hdr for chunked DIME is in buffer\n")); + soap->count += soap->dime_buflen - soap->buflen; + soap->buflen = soap->dime_buflen; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Skip padding (%ld bytes)\n", -(long)soap->dime_size&3)); + for (i = -(long)soap->dime_size&3; i > 0; i--) + { soap->bufidx++; + if (soap->bufidx >= soap->buflen) + if (soap_recv_raw(soap)) + return EOF; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME hdr for next chunk\n")); + s = (char*)tmp; + for (i = 12; i > 0; i--) + { *s++ = soap->buf[soap->bufidx++]; + if (soap->bufidx >= soap->buflen) + if (soap_recv_raw(soap)) + return EOF; + } + soap->dime_flags = tmp[0] & 0x7; + soap->dime_size = ((size_t)tmp[8] << 24) | ((size_t)tmp[9] << 16) | ((size_t)tmp[10] << 8) | ((size_t)tmp[11]); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME chunk (%u bytes)\n", (unsigned int)soap->dime_size)); + if (soap->dime_flags & SOAP_DIME_CF) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "More chunking\n")); + soap->dime_chunksize = soap->dime_size; + if (soap->buflen - soap->bufidx >= soap->dime_size) + { soap->dime_buflen = soap->buflen; + soap->buflen = soap->bufidx + soap->dime_chunksize; + } + else + soap->dime_chunksize -= soap->buflen - soap->bufidx; + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Last chunk\n")); + soap->dime_buflen = 0; + soap->dime_chunksize = 0; + } + soap->count = soap->buflen - soap->bufidx; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%u bytes remaining\n", (unsigned int)soap->count)); + return SOAP_OK; + } + if (soap->dime_chunksize) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get next DIME hdr for chunked DIME (%u bytes chunk)\n", (unsigned int)soap->dime_chunksize)); + if (soap_recv_raw(soap)) + return EOF; + if (soap->buflen - soap->bufidx >= soap->dime_chunksize) + { soap->dime_buflen = soap->buflen; + soap->count -= soap->buflen - soap->bufidx - soap->dime_chunksize; + soap->buflen = soap->bufidx + soap->dime_chunksize; + } + else + soap->dime_chunksize -= soap->buflen - soap->bufidx; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%lu bytes remaining, count=%u\n", (unsigned long)(soap->buflen-soap->bufidx), (unsigned int)soap->count)); + return SOAP_OK; + } + } +#endif + return soap_recv_raw(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +wchar +SOAP_FMAC2 +soap_getchar(struct soap *soap) +{ register wchar c; + if (soap->ahead) + { c = soap->ahead; + soap->ahead = 0; + return c; + } + return soap_get1(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +const struct soap_code_map* +SOAP_FMAC2 +soap_code(const struct soap_code_map *map, const char *str) +{ while (map->string) + { if (!strcmp(str, map->string)) + return map; + map++; + } + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +long +SOAP_FMAC2 +soap_int_code(const struct soap_code_map *map, const char *str, long other) +{ while (map->string) + { if (!strcmp(str, map->string)) + return map->code; + map++; + } + return other; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_str_code(const struct soap_code_map *map, long code) +{ while (map->code != code && map->string) + map++; + return map->string; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static wchar +soap_char(struct soap *soap) +{ char tmp[8]; + register int i; + register wchar c; + register char *s = tmp; + for (i = 0; i < 7; i++) + { c = soap_get1(soap); + if (c == ';' || (int)c == EOF) + break; + *s++ = (char)c; + } + *s = '\0'; + if (*tmp == '#') + { if (tmp[1] == 'x' || tmp[1] == 'X') + return soap_strtol(tmp + 2, NULL, 16); + return atol(tmp + 1); + } + if (!strcmp(tmp, "lt")) + return '<'; + if (!strcmp(tmp, "gt")) + return '>'; + if (!strcmp(tmp, "amp")) + return '&'; + if (!strcmp(tmp, "quot")) + return '"'; + if (!strcmp(tmp, "apos")) + return '\''; +#ifndef WITH_LEAN + return (wchar)soap_int_code(html_entity_codes, tmp, 127); +#else + return SOAP_UNKNOWN_CHAR; /* use this to represent unknown code */ +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +wchar +SOAP_FMAC2 +soap_get(struct soap *soap) +{ register wchar c; + c = soap->ahead; + if (c) + soap->ahead = 0; + else + c = soap_get1(soap); + for (;;) + { if (soap->cdata) + { if (c == ']') + { c = soap_get1(soap); + if (c == ']') + { soap->cdata = 0; + soap_get1(soap); /* skip > */ + c = soap_get1(soap); + } + else + { soap_revget1(soap); + return ']'; + } + } + else + return c; + } + switch (c) + { case '<': + do c = soap_get1(soap); + while (soap_blank(c)); + if (c == '!' || c == '?' || c == '%') + { if (c == '!') + { c = soap_get1(soap); + if (c == '[') + { do c = soap_get1(soap); + while ((int)c != EOF && c != '['); + if ((int)c == EOF) + break; + soap->cdata = 1; + c = soap_get1(soap); + continue; + } + if (c == '-' && (c = soap_get1(soap)) == '-') + { do + { c = soap_get1(soap); + if (c == '-' && (c = soap_get1(soap)) == '-') + break; + } while ((int)c != EOF); + } + } + while ((int)c != EOF && c != '>') + c = soap_get1(soap); + if ((int)c == EOF) + break; + c = soap_get1(soap); + continue; + } + if (c == '/') + return TT; + soap_revget1(soap); + return LT; + case '>': + return GT; + case '"': + return QT; + case '\'': + return AP; + case '&': + return soap_char(soap) | 0x80000000; + } + break; + } + return c; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +wchar +SOAP_FMAC2 +soap_advance(struct soap *soap) +{ register wchar c; + while ((int)((c = soap_get(soap)) != EOF) && c != LT && c != TT) + ; + return c; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +wchar +SOAP_FMAC2 +soap_skip(struct soap *soap) +{ register wchar c; + do c = soap_get(soap); + while (soap_blank(c)); + return c; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_move(struct soap *soap, long n) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving %ld bytes forward\n", (long)n)); + for (; n > 0; n--) + if ((int)soap_getchar(soap) == EOF) + return SOAP_EOF; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_tell(struct soap *soap) +{ return soap->count - soap->buflen + soap->bufidx - (soap->ahead != 0); +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_pututf8(struct soap *soap, register unsigned long c) +{ char tmp[16]; + if (c > 0 && c < 0x80) + { *tmp = (char)c; + return soap_send_raw(soap, tmp, 1); + } +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { register char *t = tmp; + if (c < 0x0800) + *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); + else + { if (c < 0x010000) + *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + else + { if (c < 0x200000) + *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + else + { if (c < 0x04000000) + *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + else + { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + } + *t++ = (char)(0x80 | (c & 0x3F)); + *t = '\0'; + } + else +#endif + sprintf(tmp, "&#%lu;", c); + return soap_send(soap, tmp); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +wchar +SOAP_FMAC2 +soap_getutf8(struct soap *soap) +{ register wchar c, c1, c2, c3, c4; + c = soap_get(soap); + if (c < 0x80) + return c; + c1 = soap_get(soap); + if (c1 < 0x80) + { soap_unget(soap, c1); + return c; + } + c1 &= 0x3F; + if (c < 0xE0) + return ((wchar)(c & 0x1F) << 6) | c1; + c2 = (wchar)soap_get1(soap) & 0x3F; + if (c < 0xF0) + return ((wchar)(c & 0x0F) << 12) | (c1 << 6) | c2; + c3 = (wchar)soap_get1(soap) & 0x3F; + if (c < 0xF8) + return ((wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3; + c4 = (wchar)soap_get1(soap) & 0x3F; + if (c < 0xFC) + return ((wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4; + return ((wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (wchar)(soap_get1(soap) & 0x3F); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_puthex(struct soap *soap, const unsigned char *s, int n) +{ /* TODO: serialize to DOM (as an option) using new soap_s2hex() */ + char d[2]; + register int i; + for (i = 0; i < n; i++) + { register int m = *s++; + d[0] = (char)((m >> 4) + (m > 159 ? '7' : '0')); + m &= 0x0F; + d[1] = (char)(m + (m > 9 ? '7' : '0')); + if (soap_send_raw(soap, d, 2)) + return soap->error; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +unsigned char* +SOAP_FMAC2 +soap_gethex(struct soap *soap, int *n) +{ +#ifdef WITH_FAST + soap->labidx = 0; + for (;;) + { register char *s; + register int i, k; + if (soap_append_lab(soap, NULL, 0)) + return NULL; + s = soap->labbuf + soap->labidx; + k = soap->lablen - soap->labidx; + soap->labidx = soap->lablen; + for (i = 0; i < k; i++) + { register char d1, d2; + register wchar c; + c = soap_get(soap); + if (soap_isxdigit(c)) + { d1 = (char)c; + c = soap_get(soap); + if (soap_isxdigit(c)) + d2 = (char)c; + else + { soap->error = SOAP_TYPE; + return NULL; + } + } + else + { unsigned char *p; + soap_unget(soap, c); + if (n) + *n = (int)(soap->lablen - k + i); + p = (unsigned char*)soap_malloc(soap, soap->lablen - k + i); + if (p) + memcpy(p, soap->labbuf, soap->lablen - k + i); + return p; + } + *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'); + } + } +#else + if (soap_new_block(soap)) + return NULL; + for (;;) + { register int i; + register char *s = (char*)soap_push_block(soap, SOAP_BLKLEN); + if (!s) + { soap_end_block(soap); + return NULL; + } + for (i = 0; i < SOAP_BLKLEN; i++) + { register char d1, d2; + register wchar c = soap_get(soap); + if (soap_isxdigit(c)) + { d1 = (char)c; + c = soap_get(soap); + if (soap_isxdigit(c)) + d2 = (char)c; + else + { soap_end_block(soap); + soap->error = SOAP_TYPE; + return NULL; + } + } + else + { unsigned char *p; + soap_unget(soap, c); + if (n) + *n = soap_size_block(soap, i); + p = (unsigned char*)soap_save_block(soap, NULL); + return p; + } + *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'); + } + } +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putbase64(struct soap *soap, const unsigned char *s, int n) +{ register int i; + register unsigned long m; + char d[4]; +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { soap->dom->data = (char*)soap_malloc(soap, (n + 2) / 3 * 4 + 1); + return soap_s2base64(soap, s, soap->dom->data, n); + } +#endif + if (!s) + return SOAP_OK; + for (; n > 2; n -= 3, s += 3) + { m = ((unsigned long)((unsigned char*)s)[0] << 16) | ((unsigned long)((unsigned char*)s)[1] << 8) | (unsigned long)((unsigned char*)s)[2]; + for (i = 4; i > 0; m >>= 6) + d[--i] = soap_base64o[m & 0x3F]; + if (soap_send_raw(soap, d, 4)) + return soap->error; + } + if (n > 0) + { m = 0; + for (i = 0; i < n; i++) + m = (m << 8) | *s++; + for (; i < 3; i++) + m <<= 8; + for (i++; i > 0; m >>= 6) + d[--i] = soap_base64o[m & 0x3F]; + for (i = 3; i > n; i--) + d[i] = '='; + if (soap_send_raw(soap, d, 4)) + return soap->error; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +unsigned char* +SOAP_FMAC2 +soap_getbase64(struct soap *soap, int *n, int malloc_flag) +{ +#ifdef WITH_FAST + soap->labidx = 0; + for (;;) + { register int i, k; + register char *s; + if (soap_append_lab(soap, NULL, 2)) + return NULL; + s = soap->labbuf + soap->labidx; + k = 3 * ((soap->lablen - soap->labidx) / 3); + soap->labidx = 3 * (soap->lablen / 3); + if (!s) + return NULL; + for (i = 0; i < k; i += 3) + { register unsigned long m = 0; + register int j = 0; + do + { register wchar c = soap_get(soap); + if (c == '=' || c < 0) + { unsigned char *p; + switch (j) + { case 2: + *s++ = (char)((m >> 4) & 0xFF); + i++; + break; + case 3: + *s++ = (char)((m >> 10) & 0xFF); + *s++ = (char)((m >> 2) & 0xFF); + i += 2; + } + if (n) + *n = (int)(soap->lablen - k + i); + p = (unsigned char*)soap_malloc(soap, soap->lablen - k + i); + if (p) + memcpy(p, soap->labbuf, soap->lablen - k + i); + if (c >= 0) + { while ((int)((c = soap_get(soap)) != EOF) && c != LT && c != TT) + ; + } + soap_unget(soap, c); + return p; + } + c -= '+'; + if (c >= 0 && c <= 79) + { m = (m << 6) + soap_base64i[c]; + j++; + } + } while (j < 4); + *s++ = (char)((m >> 16) & 0xFF); + *s++ = (char)((m >> 8) & 0xFF); + *s++ = (char)(m & 0xFF); + } + } +#else + if (soap_new_block(soap)) + return NULL; + for (;;) + { register int i; + register char *s = (char*)soap_push_block(soap, 3 * SOAP_BLKLEN); /* must be multiple of 3 */ + if (!s) + { soap_end_block(soap); + return NULL; + } + for (i = 0; i < SOAP_BLKLEN; i++) + { register unsigned long m = 0; + register int j = 0; + do + { register wchar c = soap_get(soap); + if (c == '=' || c < 0) + { unsigned char *p; + i *= 3; + switch (j) + { case 2: + *s++ = (char)((m >> 4) & 0xFF); + i++; + break; + case 3: + *s++ = (char)((m >> 10) & 0xFF); + *s++ = (char)((m >> 2) & 0xFF); + i += 2; + } + if (n) + *n = (int)soap_size_block(soap, i); + p = (unsigned char*)soap_save_block(soap, NULL); + if (c >= 0) + { while ((int)((c = soap_get(soap)) != EOF) && c != LT && c != TT) + ; + } + soap_unget(soap, c); + return p; + } + c -= '+'; + if (c >= 0 && c <= 79) + { m = (m << 6) + soap_base64i[c]; + j++; + } + } while (j < 4); + *s++ = (char)((m >> 16) & 0xFF); + *s++ = (char)((m >> 8) & 0xFF); + *s++ = (char)(m & 0xFF); + } + } +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_strdup(struct soap *soap, const char *s) +{ char *t = NULL; + if (s && (t = (char*)soap_malloc(soap, strlen(s) + 1))) + strcpy(t, s); + return t; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_new_block(struct soap *soap) +{ struct soap_blist *p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New block sequence (prev=%p)\n", soap->blist)); + if (!(p = (struct soap_blist*)SOAP_MALLOC(sizeof(struct soap_blist)))) + return SOAP_EOM; + p->next = soap->blist; + p->ptr = NULL; + p->size = 0; + soap->blist = p; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_push_block(struct soap *soap, size_t n) +{ char *p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push block of %u bytes (%u bytes total)\n", (unsigned int)n, (unsigned int)soap->blist->size)); + if (!(p = (char*)SOAP_MALLOC(n + sizeof(char*) + sizeof(size_t)))) + { soap->error = SOAP_EOM; + return NULL; + } + *(char**)p = soap->blist->ptr; + *(size_t*)(p + sizeof(char*)) = n; + soap->blist->ptr = p; + soap->blist->size += n; + return p + sizeof(char*) + sizeof(size_t); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_pop_block(struct soap *soap) +{ char *p; + if (!soap->blist->ptr) + return; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop block\n")); + p = soap->blist->ptr; + soap->blist->size -= *(size_t*)(p + sizeof(char*)); + soap->blist->ptr = *(char**)p; + SOAP_FREE(p); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static void +soap_update_ptrs(struct soap *soap, char *start, char *end, long offset) +{ int i; + register struct soap_ilist *ip; + register void *p, **q; + for (i = 0; i < SOAP_IDHASH; i++) + for (ip = soap->iht[i]; ip; ip = ip->next) + { if (ip->ptr && (char*)ip->ptr >= start && (char*)ip->ptr < end) + ip->ptr = (char*)ip->ptr + offset; + for (q = &ip->link; q; q = (void**)p) + { p = *q; + if (p && (char*)p >= start && (char*)p < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Link update id='%s' %p\n", ip->id, p)); + *q = (char*)p + offset; + } + } + for (q = &ip->copy; q; q = (void**)p) + { p = *q; + if (p && (char*)p >= start && (char*)p < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy update id='%s' %p\n", ip->id, p)); + *q = (char*)p + offset; + } + } + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +soap_has_copies(struct soap *soap, register char *start, register char *end) +{ int i; + register struct soap_ilist *ip; + register char *p; + for (i = 0; i < SOAP_IDHASH; i++) + for (ip = soap->iht[i]; ip; ip = ip->next) + for (p = (char*)ip->copy; p; p = *(char**)p) + if (p >= start && p < end) + return SOAP_ERR; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_resolve(struct soap *soap) +{ register int i; + register struct soap_ilist *ip; + short flag1 = 0, flag2; + for (i = 0; i < SOAP_IDHASH; i++) + for (ip = soap->iht[i]; ip; ip = ip->next) + { if (ip->ptr) + soap_resolve_ptr(ip); + else if (*ip->id == '#') + flag1 = 1; + } + do + { flag2 = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data\n")); + for (i = 0; i < SOAP_IDHASH; i++) + for (ip = soap->iht[i]; ip; ip = ip->next) + if (ip->copy && ip->ptr && ip->size) + if (!soap_has_copies(soap, (char*)ip->ptr, (char*)ip->ptr + ip->size)) + { register void *p, **q = (void**)ip->copy; + DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing copy chain to resolve id='%s'\n", ip->id)); + ip->copy = NULL; + do + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... copy %p -> %p (%u bytes)\n", ip->ptr, q, (unsigned int)ip->size)); + p = *q; + memcpy(q, ip->ptr, ip->size); + q = (void**)p; + } while (q); + flag2 = 1; + } + } while (flag2); + for (i = 0; i < SOAP_IDHASH; i++) + for (ip = soap->iht[i]; ip; ip = ip->next) + { register struct soap_flist *fp; + for (fp = ip->flist; fp; fp = fp->next) + if (fp->finsert) + { unsigned int k = fp->level; + void *p = ip->ptr; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded container data type=%d location=%p level=%u,%u\n", fp->type, fp->ptr, ip->level, fp->level)); + while (ip->level < k) + { void **q = (void**)soap_malloc(soap, sizeof(void*)); + if (!q) + return SOAP_EOM; + *q = p; + p = (void*)q; + k--; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); + } + fp->finsert(soap, fp->type, fp->ptr, p); + } + } + if (flag1) + return soap->error = SOAP_MISSING_ID; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_resolve_ptr(struct soap_ilist *ip) +{ register void *p, **q, *r; + q = (void**)ip->link; + ip->link = NULL; + r = ip->ptr; + while (q) + { p = *q; + *q = r; + q = (void**)p; + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_size_block(struct soap *soap, size_t n) +{ if (soap->blist->ptr) + { soap->blist->size -= *(size_t*)(soap->blist->ptr + sizeof(char*)) - n; + *(size_t*)(soap->blist->ptr + sizeof(char*)) = n; + } + return soap->blist->size; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_first_block(struct soap *soap) +{ char *p, *q, *r; + p = soap->blist->ptr; + if (!p) + return NULL; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "First block\n")); + r = NULL; + do + { q = *(char**)p; + *(char**)p = r; + r = p; + p = q; + } while (p); + soap->blist->ptr = r; + return r + sizeof(char*) + sizeof(size_t); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_next_block(struct soap *soap) +{ char *p; + p = soap->blist->ptr; + if (p) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Next block\n")); + soap->blist->ptr = *(char**)p; + SOAP_FREE(p); + if (soap->blist->ptr) + return soap->blist->ptr + sizeof(char*) + sizeof(size_t); + } + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_block_size(struct soap *soap) +{ return *(size_t*)(soap->blist->ptr + sizeof(char*)); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_end_block(struct soap *soap) +{ struct soap_blist *bp; + char *p, *q; + bp = soap->blist; + if (bp) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of block sequence, free all remaining blocks\n")); + for (p = bp->ptr; p; p = q) + { q = *(char**)p; + SOAP_FREE(p); + } + soap->blist = bp->next; + SOAP_FREE(bp); + } + DBGLOG(TEST, if (soap->blist) SOAP_MESSAGE(fdebug, "Restore previous block sequence\n")); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_save_block(struct soap *soap, char *p) +{ register size_t n; + register char *q, *s; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Save all blocks in contiguous memory space of %u bytes (%p->%p)\n", (unsigned int)soap->blist->size, soap->blist->ptr, p)); + if (soap->blist->size) + { if (!p) + p = (char*)soap_malloc(soap, soap->blist->size); + if (p) + for (s = p, q = soap_first_block(soap); q; q = soap_next_block(soap)) + { n = soap_block_size(soap); + soap_update_ptrs(soap, q, q + n, (long)s - (long)q); /* pointers s and q may or may not be related */ + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy %u bytes from %p to %p\n", (unsigned int)n, q, s)); + memcpy(s, q, n); + s += n; + } + else + soap->error = SOAP_EOM; + } + soap_end_block(soap); + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_store_block(struct soap *soap, char *p) +{ p = soap_save_block(soap, p); + if (!soap->blist) + { struct soap_ilist *ip; + int i; + for (i = 0; i < SOAP_IDHASH; i++) + for (ip = soap->iht[i]; ip; ip = ip->next) + if (ip->ptr) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolve link chain to point to %p\n", ip->ptr)); + soap_resolve_ptr(ip); + } + } + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putsize(struct soap *soap, const char *type, int size) +{ return soap_putsizes(soap, type, &size, 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putsizes(struct soap *soap, const char *type, const int *size, int dim) +{ return soap_putsizesoffsets(soap, type, size, NULL, dim); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putsizesoffsets(struct soap *soap, const char *type, const int *size, const int *offset, int dim) +{ int i; + if (!type) + return NULL; + if (soap->version == 2) + { sprintf(soap->type, "%s[%d", type, size[0]); + for (i = 1; i < dim; i++) + sprintf(soap->type + strlen(soap->type), " %d", size[i]); + } + else + { if (offset) + { sprintf(soap->type, "%s[%d", type, size[0] + offset[0]); + for (i = 1; i < dim; i++) + sprintf(soap->type + strlen(soap->type), ",%d", size[i] + offset[i]); + } + else + { sprintf(soap->type, "%s[%d", type, size[0]); + for (i = 1; i < dim; i++) + sprintf(soap->type + strlen(soap->type), ",%d", size[i]); + } + strcat(soap->type, "]"); + } + return soap->type; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putoffset(struct soap *soap, int offset) +{ return soap_putoffsets(soap, &offset, 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putoffsets(struct soap *soap, const int *offset, int dim) +{ register int i; + sprintf(soap->arrayOffset, "[%d", offset[0]); + for (i = 1; i < dim; i++) + sprintf(soap->arrayOffset + strlen(soap->arrayOffset), ",%d", offset[i]); + strcat(soap->arrayOffset, "]"); + return soap->arrayOffset; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_size(const int *size, int dim) +{ register int i, n = size[0]; + for (i = 1; i < dim; i++) + n *= size[i]; + return n; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getoffsets(const char *attr, const int *size, int *offset, int dim) +{ register int i, j = 0; + if (offset) + for (i = 0; i < dim && attr && *attr; i++) + { attr++; + j *= size[i]; + j += offset[i] = (int)atol(attr); + attr = strchr(attr, ','); + } + else + for (i = 0; i < dim && attr && *attr; i++) + { attr++; + j *= size[i]; + j += (int)atol(attr); + attr = strchr(attr, ','); + } + return j; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getsize(const char *attr1, const char *attr2, int *j) +{ register int n, k; + char *s; + *j = 0; + if (!*attr1) + return -1; + n = 1; + do + { attr1++; + k = (int)soap_strtol(attr1, &s, 10); + n *= k; + if (k < 0 || n > SOAP_MAXARRAYSIZE || s == attr1) + return -1; + attr1 = strchr(s, ','); + if (!attr1) + attr1 = strchr(s, ' '); + if (attr2 && *attr2) + { attr2++; + *j *= k; + k = (int)soap_strtol(attr2, &s, 10); + *j += k; + if (k < 0) + return -1; + attr2 = s; + } + } while (attr1 && *attr1 != ']'); + return n - *j; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getsizes(const char *attr, int *size, int dim) +{ register int i, k, n; + if (!*attr) + return -1; + i = strlen(attr); + n = 1; + do + { for (i = i-1; i >= 0; i--) + if (attr[i] == '[' || attr[i] == ',' || attr[i] == ' ') + break; + k = (int)atol(attr + i + 1); + n *= size[--dim] = k; + if (k < 0 || n > SOAP_MAXARRAYSIZE) + return -1; + } while (i >= 0 && attr[i] != '['); + return n; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getposition(const char *attr, int *pos) +{ register int i, n; + if (!*attr) + return -1; + n = 0; + i = 1; + do + { pos[n++] = (int)atol(attr + i); + while (attr[i] && attr[i] != ',' && attr[i] != ']') + i++; + if (attr[i] == ',') + i++; + } while (n < SOAP_MAXDIMS && attr[i] && attr[i] != ']'); + return n; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_push_namespace(struct soap *soap, const char *id, const char *ns) +{ register struct soap_nlist *np; + register struct Namespace *p; + np = (struct soap_nlist*)SOAP_MALLOC(sizeof(struct soap_nlist) + strlen(id)); + if (!np) + return soap->error = SOAP_EOM; + np->next = soap->nlist; + soap->nlist = np; + strcpy(np->id, id); + np->level = soap->level; + np->index = -1; + np->ns = NULL; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push namespace binding (level=%u) '%s' '%s'\n", soap->level, id, ns)); + p = soap->local_namespaces; + if (p) + { register short i = 0; + if (!strcmp(ns, soap_env1)) + soap->version = 1; /* make sure we use SOAP 1.1 */ + else if (!strcmp(ns, soap_env2)) + soap->version = 2; /* make sure we use SOAP 1.2 */ + else + { for (; p->id; p++, i++) + { if (p->ns) + if (!strcmp(ns, p->ns)) + break; + if (p->in) + if (!soap_tag_cmp(ns, p->in)) + { if (p->out) + SOAP_FREE(p->out); + if ((p->out = (char*)SOAP_MALLOC(strlen(ns) + 1))) + strcpy(p->out, ns); + break; + } + } + } + if (i == 0 && (!p->ns || strcmp(ns, p->ns))) + { if (p[0].out) + SOAP_FREE(p[0].out); + if ((p[0].out = (char*)SOAP_MALLOC(strlen(ns) + 1))) + strcpy(p[0].out, ns); + if (p[1].out) + SOAP_FREE(p[1].out); + if (soap->version == 1) + { if ((p[1].out = (char*)SOAP_MALLOC(sizeof(soap_enc1)))) + strcpy(p[1].out, soap_enc1); + } + else if ((p[1].out = (char*)SOAP_MALLOC(sizeof(soap_enc2)))) + strcpy(p[1].out, soap_enc2); + } + if (p && p->id) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push OK ('%s' matches '%s' in namespace table)\n", id, p->id)); + np->index = i; + } + } + if (!p || !p->id) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push NOT OK: no match found for '%s' in namespace mapping table (added to stack anyway)\n", ns)); + np->ns = (char*)SOAP_MALLOC(strlen(ns) + 1); + if (!np->ns) + return soap->error = SOAP_EOM; + strcpy(np->ns, ns); + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_push_default_namespace(struct soap *soap, const char *id, int n) +{ register struct soap_nlist *np = soap->nlist; + while (np && np->index >= -1) + np = np->next; + if (np && (!strncmp(np->id, id, n) && !np->id[n])) + return SOAP_OK; + np = (struct soap_nlist*)SOAP_MALLOC(sizeof(struct soap_nlist) + n); + if (!np) + return soap->error = SOAP_EOM; + np->next = soap->nlist; + soap->nlist = np; + strncpy(np->id, id, n); + np->id[n] = '\0'; + np->level = soap->level; + np->index = -2; + np->ns = NULL; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_pop_namespace(struct soap *soap) +{ register struct soap_nlist *np; + while (soap->nlist && soap->nlist->level >= soap->level) + { np = soap->nlist->next; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Popped namespace binding (level=%u) '%s'\n", soap->level, soap->nlist->id)); + if (soap->nlist->ns) + SOAP_FREE(soap->nlist->ns); + SOAP_FREE(soap->nlist); + soap->nlist = np; + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_match_namespace(struct soap *soap, const char *id1, const char *id2, int n1, int n2) +{ register struct soap_nlist *np = soap->nlist; + while (np && (np->index == -2 || (strncmp(np->id, id1, n1) || np->id[n1]))) + np = np->next; + if (np) + { if (np->index < 0 || (np->index >= 0 && soap->local_namespaces[np->index].id && (strncmp(soap->local_namespaces[np->index].id, id2, n2) || soap->local_namespaces[np->index].id[n2]))) + return SOAP_NAMESPACE; + return SOAP_OK; + } + if (n1 == 3 && n1 == n2 && !strcmp(id1, "xml") && !strcmp(id1, id2)) + return SOAP_OK; + return SOAP_SYNTAX_ERROR; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_default_namespace(struct soap *soap) +{ register struct soap_nlist *np = soap->nlist; + while (np && np->index >= -1) + np = np->next; + if (np) + return np->id; + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_tag_cmp(register const char *s, register const char *t) +{ for (; *s && *s != '"'; s++, t++) + if (tolower(*s) != tolower(*t)) + if (*t != '-') + { if (*t != '*') + return 1; + if (*++t) + { register int c = tolower(*t); + for (; *s && *s != '"'; s++) + { if (tolower(*s) == c) + if (!soap_tag_cmp(s + 1, t + 1)) + return 0; + } + break; + } + else + return 0; + } + if (*t == '*' && !t[1]) + return 0; + return *t; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_match_tag(struct soap *soap, const char *tag1, const char *tag2) +{ register const char *s, *t; + if (!tag1 || !tag2 || !*tag2) + return SOAP_OK; + s = strchr(tag1, ':'); + t = strchr(tag2, ':'); + if (t) + { if (s) + { if (SOAP_STRCMP(s + 1, t + 1)) + return SOAP_TAG_MISMATCH; + if (t != tag2 && soap_match_namespace(soap, tag1, tag2, s - tag1, t - tag2)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2)); + return SOAP_TAG_MISMATCH; + } + } + else if (SOAP_STRCMP(tag1, t + 1)) + return SOAP_TAG_MISMATCH; + else if (t != tag2 && soap_match_namespace(soap, tag1, tag2, 0, t - tag2)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2)); + return SOAP_TAG_MISMATCH; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags and (default) namespaces match: '%s' '%s'\n", tag1, tag2)); + return SOAP_OK; + } + if (s) + { if (((soap->mode & SOAP_XML_STRICT) && soap->part != SOAP_IN_HEADER && soap->encodingStyle)) + return SOAP_TAG_MISMATCH; + if (SOAP_STRCMP(s + 1, tag2)) + return SOAP_TAG_MISMATCH; + if (!soap->encodingStyle) + { t = soap_default_namespace(soap); + if (!t || soap_match_namespace(soap, tag1, t, s - tag1, strlen(t))) + return SOAP_TAG_MISMATCH; + } + } + else if (SOAP_STRCMP(tag1, tag2)) + return SOAP_TAG_MISMATCH; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags match: '%s' '%s'\n", tag1, tag2)); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_match_array(struct soap *soap, const char *type) +{ if (*soap->arrayType) + if (soap_match_tag(soap, soap->arrayType, type) + && soap_match_tag(soap, soap->arrayType, "xsd:anyType") + && soap_match_tag(soap, soap->arrayType, "xsd:ur-type") + ) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array type mismatch: '%s' '%s'\n", soap->arrayType, type)); + return SOAP_TAG_MISMATCH; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ + +#ifdef WITH_OPENSSL +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_ssl_server_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *password, const char *cafile, const char *capath, const char *dhfile, const char *randfile, const char *sid) +{ int err; + soap->keyfile = keyfile; + soap->password = password; + soap->cafile = cafile; + soap->capath = capath; + if (dhfile) + { soap->dhfile = dhfile; + soap->rsa = 0; + } + else + { soap->dhfile = NULL; + soap->rsa = 1; + } + soap->randfile = randfile; + soap->require_client_auth = (flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION); + if (!(err = soap->fsslauth(soap))) + if (sid) + SSL_CTX_set_session_id_context(soap->ctx, (unsigned char*)sid, strlen(sid)); + return err; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_ssl_client_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *password, const char *cafile, const char *capath, const char *randfile) +{ soap->keyfile = keyfile; + soap->password = password; + soap->cafile = cafile; + soap->capath = capath; + soap->dhfile = NULL; + soap->rsa = 0; + soap->randfile = randfile; + soap->require_server_auth = (flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION); + return soap->fsslauth(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static void +ssl_init() +{ static int done = 0; + if (!done) + { done = 1; + SSL_library_init(); +#ifndef WITH_LEAN + SSL_load_error_strings(); +#endif + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static const char * +ssl_error(struct soap *soap, int ret) +{ int err = SSL_get_error(soap->ssl, ret); + const char *msg = soap_str_code(h_ssl_error_codes, err); + if (msg) + strcpy(soap->msgbuf, msg); + else + return ERR_error_string(err, soap->msgbuf); + if (ERR_peek_error()) + { unsigned long r; + strcat(soap->msgbuf, "\n"); + while ((r = ERR_get_error())) + ERR_error_string_n(r, soap->msgbuf + strlen(soap->msgbuf), sizeof(soap->msgbuf) - strlen(soap->msgbuf)); + } + else + { switch (ret) + { case 0: + strcpy(soap->msgbuf, "EOF was observed that violates the protocol. The client probably provided invalid authentication information."); + break; + case -1: + sprintf(soap->msgbuf, "Error observed by underlying BIO: %s", strerror(errno)); + break; + } + } + return soap->msgbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +ssl_password(char *buf, int num, int rwflag, void *userdata) +{ if (num < (int)strlen((char*)userdata) + 1) + return 0; + return strlen(strcpy(buf, (char*)userdata)); +} +#endif + +/******************************************************************************/ +/* This callback is included for future references. It should not be deleted +#ifndef PALM_1 +static DH * +ssl_tmp_dh(SSL *ssl, int is_export, int keylength) +{ static DH *dh512 = NULL; + static DH *dh1024 = NULL; + DH *dh; + switch (keylength) + { case 512: + if (!dh512) + { BIO *bio = BIO_new_file("dh512.pem", "r"); + if (bio) + { dh512 = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + return dh512; + } + } + else + return dh512; + default: + if (!dh1024) + { BIO *bio = BIO_new_file("dh1024.pem", "r"); + if (bio) + { dh1024 = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + } + } + dh = dh1024; + } + return dh; +} +#endif +*/ +/******************************************************************************/ +#ifndef PALM_1 +static int +ssl_auth_init(struct soap *soap) +{ ssl_init(); + if (!soap->ctx) + if (!(soap->ctx = SSL_CTX_new(SSLv23_method()))) + return soap_set_receiver_error(soap, "SSL error", "Can't setup context", SOAP_SSL_ERROR); + if (soap->randfile) + { if (!RAND_load_file(soap->randfile, -1)) + return soap_set_receiver_error(soap, "SSL error", "Can't load randomness", SOAP_SSL_ERROR); + } + else if (!RAND_load_file("/dev/urandom", 1024)) + { int r; +#ifdef HAVE_RAND_R + unsigned int s = (unsigned int)time(NULL); +#endif + RAND_seed(soap->buf, sizeof(soap->buf)); + while (!RAND_status()) + { +#ifdef HAVE_RAND_R + r = rand_r(&s); +#else + r = rand(); +#endif + RAND_seed(&r, sizeof(int)); + } + } + if (soap->cafile || soap->capath) + if (!SSL_CTX_load_verify_locations(soap->ctx, soap->cafile, soap->capath)) + return soap_set_receiver_error(soap, "SSL error", "Can't read CA file and/or directory", SOAP_SSL_ERROR); + if (!SSL_CTX_set_default_verify_paths(soap->ctx)) + return soap_set_receiver_error(soap, "SSL error", "Can't read default CA file and/or directory", SOAP_SSL_ERROR); + if (soap->keyfile) + { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile)) + return soap_set_receiver_error(soap, "SSL error", "Can't read certificate key file", SOAP_SSL_ERROR); + if (soap->password) + { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password); + SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password); + if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM)) + return soap_set_receiver_error(soap, "SSL error", "Can't read key file", SOAP_SSL_ERROR); + } + } + if (soap->rsa) + { RSA *rsa = RSA_generate_key(512, RSA_F4, NULL, NULL); + if (!SSL_CTX_set_tmp_rsa(soap->ctx, rsa)) + { if (rsa) + RSA_free(rsa); + return soap_set_receiver_error(soap, "SSL error", "Can't set RSA key", SOAP_SSL_ERROR); + } + RSA_free(rsa); + } + else if (soap->dhfile) + { DH *dh = 0; + BIO *bio; + bio = BIO_new_file(soap->dhfile, "r"); + if (!bio) + return soap_set_receiver_error(soap, "SSL error", "Can't read DH file", SOAP_SSL_ERROR); + dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + if (SSL_CTX_set_tmp_dh(soap->ctx, dh) < 0) + { if (dh) + DH_free(dh); + return soap_set_receiver_error(soap, "SSL error", "Can't set DH parameters", SOAP_SSL_ERROR); + } + DH_free(dh); + } + SSL_CTX_set_options(soap->ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2); + SSL_CTX_set_verify(soap->ctx, soap->require_client_auth ? (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT) : soap->require_server_auth ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, soap->fsslverify); +#if (OPENSSL_VERSION_NUMBER < 0x00905100L) + SSL_CTX_set_verify_depth(soap->ctx, 1); +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +ssl_verify_callback(int ok, X509_STORE_CTX *store) +{ +#ifdef SOAP_DEBUG + if (!ok) + { char data[256]; + X509 *cert = X509_STORE_CTX_get_current_cert(store); + fprintf(stderr, "SSL Verify error with certificate at depth %d: %s\n", X509_STORE_CTX_get_error_depth(store), X509_verify_cert_error_string(X509_STORE_CTX_get_error(store))); + X509_NAME_oneline(X509_get_issuer_name(cert), data, sizeof(data)); + fprintf(stderr, "certificate issuer %s\n", data); + X509_NAME_oneline(X509_get_subject_name(cert), data, sizeof(data)); + fprintf(stderr, "certificate subject %s\n", data); + } +#endif + return ok; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_ssl_accept(struct soap *soap) +{ int i, r; + if (!soap_valid_socket(soap->socket)) + return soap_set_receiver_error(soap, "SSL error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR); + if (!soap->ssl) + { soap->ssl = SSL_new(soap->ctx); + if (!soap->ssl) + return soap_set_receiver_error(soap, "SSL error", "SSL_new() failed in soap_ssl_accept()", SOAP_SSL_ERROR); + } + else + SSL_clear(soap->ssl); + soap->imode |= SOAP_ENC_SSL; + soap->omode |= SOAP_ENC_SSL; +#ifdef WIN32 + u_long nonblocking = 1; + ioctlsocket((SOAP_SOCKET)soap->socket, FIONBIO, &nonblocking); +#else + fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL)|O_NONBLOCK); +#endif + soap->bio = BIO_new_socket((SOAP_SOCKET)soap->socket, BIO_NOCLOSE); + SSL_set_bio(soap->ssl, soap->bio, soap->bio); + i = 100; + while ((r = SSL_accept(soap->ssl)) <= 0) + { int err = SSL_get_error(soap->ssl, r); + if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) + { struct timeval timeout; + fd_set fd; + if (i-- <= 0) + break; + timeout.tv_sec = 0; + timeout.tv_usec = 100000; + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->socket, &fd); + r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout); + if (r < 0 && soap_socket_errno != SOAP_EINTR) + { soap->errnum = soap_socket_errno; + return SOAP_EOF; + } + } + else + { soap->errnum = err; + break; + } + } +#ifdef WIN32 + { u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)soap->socket, FIONBIO, &blocking); + } +#else + fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL)&~O_NONBLOCK); +#endif + if (r <= 0) + { soap_set_receiver_error(soap, ssl_error(soap, r), "SSL_accept() failed in soap_ssl_accept()", SOAP_SSL_ERROR); + soap_closesock(soap); + return SOAP_SSL_ERROR; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#endif /* WITH_OPENSSL */ + +/******************************************************************************/ +#ifndef PALM_1 +static int +tcp_init(struct soap *soap) +{ soap->errmode = 1; +#ifdef WIN32 + if (tcp_done) + return 0; + else + { WSADATA w; + if (WSAStartup(MAKEWORD(1, 1), &w)) + return -1; + tcp_done = 1; + } +#endif +#ifdef PALM + errno = 0; + h_errno = 0; + AppNetRefnum = 0; + NetUInit(); + AppNetTimeout = 10000; + NetLibOpen(AppNetRefnum, &h_errno); +#endif + return 0; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_done(struct soap *soap) +{ +#ifndef WITH_LEAN + int i; +#endif + soap_free(soap); + while (soap->clist) + { struct soap_clist *p = soap->clist->next; + SOAP_FREE(soap->clist); + soap->clist = p; + } + soap->keep_alive = 0; /* to force close the socket */ + soap_closesock(soap); +#ifdef WITH_COOKIES + soap_free_cookies(soap); +#endif + while (soap->plugins) + { register struct soap_plugin *p = soap->plugins->next; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Removing plugin '%s'\n", soap->plugins->id)); + if (soap->plugins->fcopy || !soap->copy) + soap->plugins->fdelete(soap, soap->plugins); + SOAP_FREE(soap->plugins); + soap->plugins = p; + } + soap->fplugin = fplugin; + soap->fpost = http_post; + soap->fget = http_get; + soap->fposthdr = http_post_header; + soap->fresponse = http_response; + soap->fparse = http_parse; + soap->fparsehdr = http_parse_header; +#ifndef MAC_CARBON + soap->faccept = tcp_accept; + soap->fopen = tcp_connect; + soap->fclose = tcp_disconnect; + soap->fsend = fsend; + soap->frecv = frecv; +#endif + soap->fprepare = NULL; + soap->fignore = NULL; +#ifdef WITH_OPENSSL + if (soap->session) + { SSL_SESSION_free(soap->session); + soap->session = NULL; + } +#endif + if (!soap->copy) + { if (soap_valid_socket(soap->master)) + { closesocket((SOAP_SOCKET)soap->master); + soap->master = SOAP_INVALID_SOCKET; + } +#ifdef WITH_OPENSSL + if (soap->ctx) + { SSL_CTX_free(soap->ctx); + soap->ctx = NULL; + } +#endif + } +#ifndef WITH_LEAN + for (i = 0; i < SOAP_MAXLOGS; i++) + { soap_close_logfile(soap, i); + if (soap->logfile[i]) + { SOAP_FREE((void*)soap->logfile[i]); + soap->logfile[i] = NULL; + } + } +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_cleanup(struct soap *soap) +{ soap_done(soap); +#ifdef WIN32 + if (!tcp_done) + return; + tcp_done = 0; + WSACleanup(); +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static const char* +tcp_error(struct soap *soap) +{ register const char *msg = NULL; + switch (soap->errmode) + { case 0: + msg = soap_strerror(soap); + break; + case 1: + msg = "WSAStartup failed"; + break; + case 2: + { +#ifndef WITH_LEAN + msg = soap_str_code(h_error_codes, soap->errnum); + if (!msg) +#endif + { sprintf(soap->msgbuf, "TCP error %d", soap->errnum); + msg = soap->msgbuf; + } + } + } + return msg; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static const char* +http_error(struct soap *soap, int status) +{ register const char *msg = NULL; +#ifndef WITH_LEAN + msg = soap_str_code(h_http_error_codes, status); + if (!msg) +#endif + { sprintf(soap->msgbuf, "HTTP error %d", status); + msg = soap->msgbuf; + } + return msg; +} +#endif + +/******************************************************************************/ +/* WR[ */ +#ifndef WITH_IPV6 +/* ]WR */ +#ifndef MAC_CARBON +#ifndef PALM_1 +static int +soap_gethost(struct soap *soap, const char *addr, struct in_addr *inaddr) +{ unsigned long iadd; + struct hostent hostent, *host = &hostent; +/* WR[ */ +#ifdef VXWORKS + int hostint; + char * addrcopy = (char*)malloc(strlen(addr) + 1); /*copy of addr. */ + /* inet_addr(), and hostGetByName() expect "char *"; addr is a "const char *". */ + strncpy(addrcopy, addr, strlen(addr)+1); + iadd = inet_addr(addrcopy); +#else +/* ]WR */ +#if defined(_AIXVERSION_431) || defined(TRU64) + struct hostent_data ht_data; +#endif + iadd = inet_addr(addr); +/* WR[ */ +#endif +/* ]WR */ + if ((int)iadd != -1) + { memcpy(inaddr, &iadd, sizeof(iadd)); +/* WR[ */ +#ifdef VXWORKS + free(addrcopy); +#endif +/* ]WR */ + return 0; + } +#if defined(__GLIBC__) + if (gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &host, &soap->errnum) < 0) + host = NULL; +#elif defined(_AIXVERSION_431) || defined(TRU64) + memset(&ht_data, 0, sizeof(ht_data)); + if (gethostbyname_r(addr, &hostent, &ht_data) < 0) + { host = NULL; + soap->errnum = h_errno; + } +#elif defined(HAVE_GETHOSTBYNAME_R) + host = gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &soap->errnum); +/* WR[ */ +#elif defined(VXWORKS) + /* If the DNS resolver library resolvLib has been configured in the vxWorks + * image, a query for the host IP address is sent to the DNS server, if the + * name was not found in the local host table. */ + hostint = hostGetByName(addrcopy); + if (hostint == ERROR) + { + host = NULL; + soap->errnum = soap_errno; + } + free(addrcopy); /*free() is placed after the error checking to assure that + * errno captured is that from hostGetByName() */ +/* ]WR */ +#else + if (!(host = gethostbyname(addr))) + soap->errnum = h_errno; +#endif + if (!host) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Host name not found\n")); + return -1; + } +/* WR[ */ +#ifdef VXWORKS + inaddr->s_addr = hostint; +#else +/* ]WR */ + memcpy(inaddr, host->h_addr, host->h_length); +/* WR[ */ +#endif +/* ]WR */ + return 0; +} +#endif +#endif +/* WR[ */ +#endif /* WITH_IPV6 */ +/* ]WR */ + +/******************************************************************************/ +#ifndef MAC_CARBON +#ifndef PALM_1 +static int +tcp_connect(struct soap *soap, const char *endpoint, const char *host, int port) +{ struct sockaddr_in sockaddr; +/* WR[ */ +#ifdef WITH_IPV6 + struct addrinfo *addrinfo; + struct addrinfo hints; + struct addrinfo resaddr; + struct sockaddr_storage addrstorage; + int err; +#endif /* WITH_IPV6 */ +/* ]WR */ + register int fd; +#ifndef WITH_LEAN + int len = SOAP_BUFLEN; + int set = 1; +#endif + if (soap_valid_socket(soap->socket)) + closesocket((SOAP_SOCKET)soap->socket); + soap->socket = SOAP_INVALID_SOCKET; + if (tcp_init(soap)) + { soap_set_sender_error(soap, tcp_error(soap), "TCP initialization failed in tcp_connect()", SOAP_TCP_ERROR); + return -1; + } + soap->errmode = 0; +/* WR[ */ +#ifdef WITH_IPV6 + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + soap->errmode = 2; + if (soap->proxy_host) + err = getaddrinfo(soap->proxy_host, soap_int2s(soap, soap->proxy_port), &hints, &addrinfo); + else + err = getaddrinfo(host, soap_int2s(soap, port), &hints, &addrinfo); + if (addrinfo) + { resaddr = *addrinfo; + addrstorage = *((struct sockaddr_storage *) addrinfo->ai_addr); + resaddr.ai_addr = (struct sockaddr *) &addrstorage; + freeaddrinfo(addrinfo); + } + if (err) + { soap_set_sender_error(soap, gai_strerror(err), + "TCP getaddrinfo on proxy host failed in tcp_connect()", SOAP_TCP_ERROR); + return -1; + } + fd = (int)socket(resaddr.ai_family, resaddr.ai_socktype, resaddr.ai_protocol); /* modified to use fd */ + soap->errmode = 0; +#else /* WITH_IPV6 */ +/* ]WR */ + fd = (int)socket(AF_INET, SOCK_STREAM, 0); +/* WR[ */ +#endif /* WITH_IPV6 */ +/* ]WR */ + if (fd < 0) + { soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "TCP socket failed in tcp_connect()", SOAP_TCP_ERROR); + return -1; + } +#ifndef WITH_LEAN + if (soap->connect_flags & SO_LINGER) + { struct linger linger; + memset(&linger, 0, sizeof(struct linger)); + linger.l_onoff = 1; + linger.l_linger = 0; + if (setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger))) + { soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "TCP setsockopt SO_LINGER failed in tcp_connect()", SOAP_TCP_ERROR); + closesocket((SOAP_SOCKET)fd); + return -1; + } + } + if ((soap->connect_flags & ~SO_LINGER) && setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, soap->connect_flags & ~SO_LINGER, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "TCP setsockopt failed in tcp_connect()", SOAP_TCP_ERROR); + closesocket((SOAP_SOCKET)fd); + return -1; + } + if (soap->keep_alive && setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "TCP setsockopt SO_KEEPALIVE failed in tcp_connect()", SOAP_TCP_ERROR); + closesocket((SOAP_SOCKET)fd); + return -1; + } + if (setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "TCP setsockopt SO_SNDBUF failed in tcp_connect()", SOAP_TCP_ERROR); + closesocket((SOAP_SOCKET)fd); + return -1; + } + if (setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "TCP setsockopt SO_RCVBUF failed in tcp_connect()", SOAP_TCP_ERROR); + closesocket((SOAP_SOCKET)fd); + return -1; + } +#ifdef TCP_NODELAY + if (setsockopt((SOAP_SOCKET)fd, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "TCP setsockopt TCP_NODELAY failed in tcp_connect()", SOAP_TCP_ERROR); + closesocket((SOAP_SOCKET)fd); + return -1; + } +#endif +#endif +/* WR[ */ +#ifndef WITH_IPV6 +/* ]WR */ + memset(&sockaddr, 0, sizeof(sockaddr)); + sockaddr.sin_family = AF_INET; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Open socket %d to host='%s'\n", fd, host)); + soap->errmode = 2; + if (soap->proxy_host) + { if (soap_gethost(soap, soap->proxy_host, &sockaddr.sin_addr)) + { soap_set_sender_error(soap, tcp_error(soap), "TCP get proxy host by name failed in tcp_connect()", SOAP_TCP_ERROR); + closesocket((SOAP_SOCKET)fd); + return -1; + } + sockaddr.sin_port = htons((short)soap->proxy_port); + } + else + { if (soap_gethost(soap, host, &sockaddr.sin_addr)) + { soap_set_sender_error(soap, tcp_error(soap), "TCP get host by name failed in tcp_connect()", SOAP_TCP_ERROR); + closesocket((SOAP_SOCKET)fd); + return -1; + } + sockaddr.sin_port = htons((short)port); + } + soap->errmode = 0; +/* WR[ */ +#endif /* WITH_IPV6 */ +/* ]WR */ +#ifndef WITH_LEAN + if (soap->connect_timeout) +#if defined(WIN32) + { u_long nonblocking = 1; + ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &nonblocking); + } +/* WR[ */ +#elif defined(VXWORKS) + { + vx_nonblocking = TRUE; + ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&vx_nonblocking)); /* modified to use fd */ + } +/* ]WR */ +#else + fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)|O_NONBLOCK); +#endif + else +#if defined(WIN32) + { u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &blocking); + } +/* WR[ */ +#elif defined(VXWORKS) + { + vx_nonblocking = FALSE; + ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&vx_nonblocking)); /* modified to use fd */ + } +/* ]WR */ +#else + fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)&~O_NONBLOCK); +#endif +#endif + for (;;) + { +/* WR[ */ +#ifdef WITH_IPV6 + if (connect((SOAP_SOCKET)fd, resaddr.ai_addr, resaddr.ai_addrlen)) /* modified to use fd */ +#else /* WITH_IPV6 */ + if (connect((SOAP_SOCKET)fd, (struct sockaddr*)&sockaddr, sizeof(sockaddr))) +#endif /* WITH_IPV6 */ +/* ]WR */ + { +#ifndef WITH_LEAN + if (soap->connect_timeout && (soap_socket_errno == SOAP_EINPROGRESS || soap_socket_errno == SOAP_EWOULDBLOCK)) + { struct timeval timeout; +#if defined(SOCKLEN_T) + SOCKLEN_T n = sizeof(struct sockaddr_in); +#elif defined(__socklen_t_defined) || defined(_SOCKLEN_T) || defined(CYGWIN) + socklen_t n = sizeof(struct sockaddr_in); +#elif defined(WIN32) || defined(__APPLE__) || defined(HP_UX) || defined(SUN_OS) || defined(OPENSERVER) || defined(TRU64) || defined(VXWORKS) + int n = sizeof(struct sockaddr_in); +#else + size_t n = sizeof(struct sockaddr_in); +#endif + fd_set fds; + if (soap->connect_timeout > 0) + { timeout.tv_sec = soap->connect_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->connect_timeout/1000000; + timeout.tv_usec = -soap->connect_timeout%1000000; + } + FD_ZERO(&fds); + FD_SET((SOAP_SOCKET)fd, &fds); + for (;;) + { int r = select((SOAP_SOCKET)(fd + 1), NULL, &fds, NULL, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n")); + soap_set_sender_error(soap, "Timeout", "TCP connect failed in tcp_connect()", SOAP_TCP_ERROR); + closesocket((SOAP_SOCKET)fd); + return -1; + } + if (soap_socket_errno != SOAP_EINTR) + { soap->errnum = soap_socket_errno; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); + soap_set_sender_error(soap, tcp_error(soap), "TCP connect failed in tcp_connect()", SOAP_TCP_ERROR); + closesocket((SOAP_SOCKET)fd); + return -1; + } + } + n = sizeof(soap->errnum); + if (!getsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_ERROR, (char*)&soap->errnum, &n) && !soap->errnum) + break; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); + soap_set_sender_error(soap, tcp_error(soap), "TCP connect failed in tcp_connect()", SOAP_TCP_ERROR); + closesocket((SOAP_SOCKET)fd); + return -1; + } + else +#endif + if (soap_socket_errno != SOAP_EINTR) + { soap->errnum = soap_socket_errno; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); + soap_set_sender_error(soap, tcp_error(soap), "TCP connect failed in tcp_connect()", SOAP_TCP_ERROR); + closesocket((SOAP_SOCKET)fd); + return -1; + } + } + else + break; + } +#ifndef WITH_LEAN + if (soap->connect_timeout) +#if defined(WIN32) + { u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &blocking); + } +/* WR[ */ +#elif defined(VXWORKS) + { + vx_nonblocking = FALSE; + ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&vx_nonblocking)); /* modified to use fd */ + } +/* ]WR */ +#else + fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)&~O_NONBLOCK); +#endif +#endif + soap->socket = fd; +#ifdef WITH_OPENSSL + soap->imode &= ~SOAP_ENC_SSL; + soap->omode &= ~SOAP_ENC_SSL; + if (!strncmp(endpoint, "https:", 6)) + { int r; + if (soap->proxy_host) + { unsigned int k = soap->omode; /* make sure we only parse HTTP */ + size_t n = soap->count; /* save the content length */ + soap->omode &= ~0xFF; /* mask IO and ENC */ + soap->omode |= SOAP_IO_BUFFER; + soap_begin_send(soap); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connecting to proxy server\n")); + sprintf(soap->tmpbuf, "CONNECT %s:%d HTTP/%s", host, port, soap->http_version); + if ((soap->error = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return -1; +#ifndef WITH_LEAN + if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761) + { sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd); + strcpy(soap->tmpbuf, "Basic "); + soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, strlen(soap->tmpbuf + 262)); + if ((soap->error = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf))) + return soap->error; + } +#endif + if ((soap->error = soap->fposthdr(soap, NULL, NULL)) + || soap_flush(soap)) + return -1; + soap->omode = k; + k = soap->imode; + soap->imode &= ~0xFF; /* mask IO and ENC */ + if (soap_begin_recv(soap)) + return -1; + soap->imode = k; + soap->count = n; + soap_begin_send(soap); + } + if (!soap->ctx && (soap->error = soap->fsslauth(soap))) + { soap_set_sender_error(soap, "SSL error", "SSL authentication failed in tcp_connect(): check password, key file, and ca file.", SOAP_SSL_ERROR); + return -1; + } + soap->ssl = SSL_new(soap->ctx); + if (!soap->ssl) + { soap->error = SOAP_SSL_ERROR; + return -1; + } + if (soap->session) + { if (!strcmp(soap->session_host, host) && soap->session_port == port) + SSL_set_session(soap->ssl, soap->session); + SSL_SESSION_free(soap->session); + soap->session = NULL; + } + soap->imode |= SOAP_ENC_SSL; + soap->omode |= SOAP_ENC_SSL; + soap->bio = BIO_new_socket((SOAP_SOCKET)fd, BIO_NOCLOSE); + SSL_set_bio(soap->ssl, soap->bio, soap->bio); +#ifndef WITH_LEAN + if (soap->connect_timeout) +#ifdef WIN32 + { u_long nonblocking = 1; + ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &nonblocking); + } +#else + fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)|O_NONBLOCK); +#endif +#endif + for (;;) + { if ((r = SSL_connect(soap->ssl)) <= 0) + { int err = SSL_get_error(soap->ssl, r); + if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) + { soap_set_sender_error(soap, ssl_error(soap, r), "SSL connect failed in tcp_connect()", SOAP_SSL_ERROR); + return -1; + } + if (soap->connect_timeout) + { struct timeval timeout; + fd_set fds; + if (soap->connect_timeout > 0) + { timeout.tv_sec = soap->connect_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->connect_timeout/1000000; + timeout.tv_usec = -soap->connect_timeout%1000000; + } + FD_ZERO(&fds); + FD_SET((SOAP_SOCKET)(soap->socket), &fds); + for (;;) + { int r = select((SOAP_SOCKET)(soap->socket + 1), &fds, NULL, &fds, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n")); + soap_set_sender_error(soap, "Timeout", "TCP connect failed in tcp_connect()", SOAP_TCP_ERROR); + return -1; + } + } + continue; + } + } + break; + } +#ifndef WITH_LEAN + if (soap->connect_timeout) +#ifdef WIN32 + { u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &blocking); + } +#else + fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)&~O_NONBLOCK); +#endif +#endif + if (soap->require_server_auth) + { X509 *peer; + int err; + if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK) + { soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL certificate cannot be verified in tcp_connect()", SOAP_SSL_ERROR); + return -1; + } + peer = SSL_get_peer_certificate(soap->ssl); + if (!peer) + { soap_set_sender_error(soap, "SSL error", "No SSL certificate was presented by the peer in tcp_connect()", SOAP_SSL_ERROR); + return -1; + } + X509_NAME_get_text_by_NID(X509_get_subject_name(peer), NID_commonName, soap->msgbuf, sizeof(soap->msgbuf)); + X509_free(peer); + if (soap_tag_cmp(soap->msgbuf, host)) + { soap_set_sender_error(soap, "SSL error", "SSL certificate host name mismatch in tcp_connect()", SOAP_SSL_ERROR); + return -1; + } + } + } +#endif + return fd; +} +#endif +#endif + +/******************************************************************************/ +#ifndef MAC_CARBON +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_bind(struct soap *soap, const char *host, int port, int backlog) +{ struct sockaddr_in sockaddr; +/* WR[ */ +#ifdef WITH_IPV6 + struct addrinfo *addrinfo; + struct addrinfo hints; + struct addrinfo resaddr; + struct sockaddr_storage addrstorage; + int err; +#endif /* WITH_IPV6 */ +/* ]WR */ +#ifndef WITH_LEAN + int len = SOAP_BUFLEN; + int set = 1; +#endif + if (soap_valid_socket(soap->master)) + { closesocket((SOAP_SOCKET)soap->master); + soap->master = SOAP_INVALID_SOCKET; + } + soap->socket = SOAP_INVALID_SOCKET; + soap->errmode = 1; + if (tcp_init(soap)) + { soap_set_receiver_error(soap, tcp_error(soap), "TCP init failed in soap_bind()", SOAP_TCP_ERROR); + return -1; + } +/* WR[ */ +#ifdef WITH_IPV6 + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + soap->errmode = 2; + if (host) + err = getaddrinfo(host, soap_int2s(soap, port), &hints, &addrinfo); + else + err = getaddrinfo(NULL, soap_int2s(soap, port), &hints, &addrinfo); + if (NULL != addrinfo) + { + resaddr = *addrinfo; + addrstorage = *((struct sockaddr_storage *) addrinfo->ai_addr); + resaddr.ai_addr = (struct sockaddr *) &addrstorage; + freeaddrinfo(addrinfo); + } + if (err) + { soap_set_receiver_error(soap, gai_strerror(err), "TCP getaddrinfo failed in soap_bind()", SOAP_TCP_ERROR); + return -1; + } + soap->errmode = 0; + if ((soap->master = socket(resaddr.ai_family, resaddr.ai_socktype, resaddr.ai_protocol)) < 0) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP socket failed in soap_bind()", SOAP_TCP_ERROR); + return -1; + } +#else /* WITH_IPV6 */ +/* ]WR */ + soap->errmode = 0; + if ((soap->master = (int)socket(AF_INET, SOCK_STREAM, 0)) < 0) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP socket failed in soap_bind()", SOAP_TCP_ERROR); + return -1; + } +/* WR[ */ +#endif /* WITH_IPV6 */ +/* ]WR */ +#ifndef WITH_LEAN + if (soap->bind_flags && setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, soap->bind_flags, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt failed in soap_bind()", SOAP_TCP_ERROR); + return -1; + } + if (soap->keep_alive && setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt SO_KEEPALIVE failed in soap_bind()", SOAP_TCP_ERROR); + return -1; + } + if (setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt SO_SNDBUF failed in soap_bind()", SOAP_TCP_ERROR); + return -1; + } + if (setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt SO_RCVBUF failed in soap_bind()", SOAP_TCP_ERROR); + return -1; + } +#ifdef TCP_NODELAY + if (setsockopt((SOAP_SOCKET)soap->master, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt TCP_NODELAY failed in soap_bind()", SOAP_TCP_ERROR); + return -1; + } +#endif +#endif +/* WR[ */ +#ifdef WITH_IPV6 + soap->errmode = 0; + if (bind(soap->master, resaddr.ai_addr, resaddr.ai_addrlen) || listen(soap->master, backlog)) + { + soap->errnum = soap_socket_errno; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n")); + soap_closesock(soap); + soap_set_receiver_error(soap, tcp_error(soap), "TCP bind failed in soap_bind()", SOAP_TCP_ERROR); + return -1; + } +#else /* WITH_IPV6 */ +/* ]WR */ + memset(&sockaddr, 0, sizeof(sockaddr)); + sockaddr.sin_family = AF_INET; + soap->errmode = 2; + if (host) + { if (soap_gethost(soap, host, &sockaddr.sin_addr)) + { soap_set_receiver_error(soap, tcp_error(soap), "TCP get host by name failed in soap_bind()", SOAP_TCP_ERROR); + return -1; + } + } + else + sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); + sockaddr.sin_port = htons((short)port); + soap->errmode = 0; + if (bind((SOAP_SOCKET)soap->master, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) || listen((SOAP_SOCKET)soap->master, backlog)) + { soap->errnum = soap_socket_errno; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n")); + soap_closesock(soap); + soap_set_receiver_error(soap, tcp_error(soap), "TCP bind failed in soap_bind()", SOAP_TCP_ERROR); + return -1; + } +/* WR[ */ +#endif /* WITH_IPV6 */ +/* ]WR */ +#ifdef WITH_OPENSSL + if (!soap->ctx && (soap->error = soap->fsslauth(soap))) + return -1; +#endif + return soap->master; +} +#endif +#endif + +/******************************************************************************/ +#ifndef MAC_CARBON +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_poll(struct soap *soap) +{ +#ifndef WITH_LEAN + struct timeval timeout; + fd_set sfd,rfd; + int r; + timeout.tv_sec = 0; + timeout.tv_usec = 0; + FD_ZERO(&rfd); + FD_ZERO(&sfd); + if (soap->socket >= 0) + { FD_SET(soap->socket, &rfd); + FD_SET(soap->socket, &sfd); + r = select(soap->socket + 1, &rfd, &sfd, NULL, &timeout); + } + else if (soap->master >= 0) + { FD_SET(soap->master, &rfd); + r = select(soap->master + 1, &rfd, &sfd, NULL, &timeout); + } + else + { FD_SET(soap->sendfd, &sfd); + FD_SET(soap->recvfd, &rfd); + r = select((soap->sendfd > soap->recvfd ? soap->sendfd : soap->recvfd) + 1, &rfd, &sfd, NULL, &timeout); + } + if (r > 0) + { +#ifdef WITH_OPENSSL + if (soap->ssl) + { if ((soap->socket >= 0) && FD_ISSET(soap->socket, &rfd)) + { char buf = '\0'; + if (SSL_peek(soap->ssl, &buf, 1) <= 0) + return SOAP_EOF; + } + } +#endif + return SOAP_OK; + } + if (r < 0 && (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) && soap_socket_errno != SOAP_EINTR) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "select failed in soap_poll()", SOAP_TCP_ERROR); + return soap->error = SOAP_TCP_ERROR; + } + else + soap->errnum = soap_errno; + return SOAP_EOF; +#else + return SOAP_OK; +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef MAC_CARBON +#ifndef PALM_1 +static int +tcp_accept(struct soap *soap, int s, struct sockaddr *a, int *n) +{ +#if defined(SOCKLEN_T) + return (int)accept((SOAP_SOCKET)s, a, (SOCKLEN_T*)n); +#elif defined(__socklen_t_defined) || defined(_SOCKLEN_T) || defined(CYGWIN) + return (int)accept((SOAP_SOCKET)s, a, (socklen_t*)n); +#elif defined(WIN32) || defined(__APPLE__) || defined(HP_UX) || defined(SUN_OS) || defined(OPENSERVER) || defined(TRU64) || defined(VXWORKS) + return (int)accept((SOAP_SOCKET)s, a, n); +#else + return (int)accept((SOAP_SOCKET)s, a, (size_t*)n); +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef MAC_CARBON +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_accept(struct soap *soap) +{ +/* WR[ */ +#ifdef WITH_IPV6 + struct sockaddr_storage sockaddr; +#else /* WITH_IPV6 */ +/* ]WR */ + struct sockaddr_in sockaddr; +/* WR[ */ +#endif +/* ]WR */ + int n = (int)sizeof(struct sockaddr); +#ifndef WITH_LEAN + int len = SOAP_BUFLEN; + int set = 1; +#endif + memset(&sockaddr, 0, sizeof(sockaddr)); + soap->socket = SOAP_INVALID_SOCKET; + soap->errmode = 0; + if (soap_valid_socket(soap->master)) + { for (;;) + { +#ifndef WITH_LEAN + if (soap->accept_timeout) + { struct timeval timeout; + fd_set fd; + if (soap->accept_timeout > 0) + { timeout.tv_sec = soap->accept_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->accept_timeout/1000000; + timeout.tv_usec = -soap->accept_timeout%1000000; + } + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->master, &fd); + for (;;) + { int r = select((SOAP_SOCKET)(soap->master + 1), &fd, &fd, NULL, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + soap_set_receiver_error(soap, "Timeout", "TCP accept failed in soap_accept()", SOAP_TCP_ERROR); + return -1; + } + if (soap_socket_errno != SOAP_EINTR) + { soap->errnum = soap_socket_errno; + soap_closesock(soap); + soap_set_sender_error(soap, tcp_error(soap), "TCP accept failed in soap_accept()", SOAP_TCP_ERROR); + return -1; + } + } +#if defined(WIN32) + { u_long nonblocking = 1; + ioctlsocket((SOAP_SOCKET)soap->master, FIONBIO, &nonblocking); + } +#elif defined(VXWORKS) + { vx_nonblocking = TRUE; + ioctl((SOAP_SOCKET)soap->master, FIONBIO, (int)(&vx_nonblocking)); + } +#else + fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL)|O_NONBLOCK); +#endif + } + else +#if defined(WIN32) + { u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)soap->master, FIONBIO, &blocking); + } +/* WR[ */ +#elif defined(VXWORKS) + { + vx_nonblocking = FALSE; + ioctl((SOAP_SOCKET)soap->master, FIONBIO, (int)(&vx_nonblocking)); + } +/* ]WR */ +#else + fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL)&~O_NONBLOCK); +#endif +#endif + if ((soap->socket = soap->faccept(soap, soap->master, (struct sockaddr*)&sockaddr, &n)) >= 0) + { +/* WR[ */ +#ifdef WITH_IPV6 +/* Use soap->host to store the numeric form of the remote host */ + getnameinfo((struct sockaddr*)&sockaddr, n, soap->host, sizeof(soap->host), NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV); + soap->ip = 0; /* info stored in soap->host */ + soap->port = 0; /* info stored in soap->host */ +#else /* WITH_IPV6 */ +/* ]WR */ + soap->ip = ntohl(sockaddr.sin_addr.s_addr); + soap->port = (int)ntohs(sockaddr.sin_port); +/* WR[ */ +#endif /* WITH_IPV6 */ +/* ]WR */ + soap->keep_alive = ((soap->imode & SOAP_IO_KEEPALIVE) != 0); +#ifndef WITH_LEAN + if (soap->accept_flags & SO_LINGER) + { struct linger linger; + memset(&linger, 0, sizeof(struct linger)); + linger.l_onoff = 1; + linger.l_linger = 0; + if (setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt SO_LINGER failed in soap_accept()", SOAP_TCP_ERROR); + return -1; + } + } + if ((soap->accept_flags & ~SO_LINGER) && setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, soap->accept_flags & ~SO_LINGER, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt failed in soap_accept()", SOAP_TCP_ERROR); + return -1; + } + if (soap->keep_alive && setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt SO_KEEPALIVE failed in soap_accept()", SOAP_TCP_ERROR); + return -1; + } + if (setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt SO_SNDBUF failed in soap_accept()", SOAP_TCP_ERROR); + return -1; + } + if (setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt SO_RCVBUF failed in soap_accept()", SOAP_TCP_ERROR); + return -1; + } +#ifdef TCP_NODELAY + if (setsockopt((SOAP_SOCKET)soap->socket, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt TCP_NODELAY failed in soap_accept()", SOAP_TCP_ERROR); + return -1; + } +#endif +#endif + if (soap->accept_timeout) + { +#if defined(WIN32) + u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)soap->master, FIONBIO, &blocking); + ioctlsocket((SOAP_SOCKET)soap->socket, FIONBIO, &blocking); +/* WR[ */ +#elif defined(VXWORKS) + vx_nonblocking = FALSE; + ioctl((SOAP_SOCKET)soap->master, FIONBIO, (int)(&vx_nonblocking)); + ioctl((SOAP_SOCKET)soap->socket, FIONBIO, (int)(&vx_nonblocking)); +/* ]WR */ +#else + fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL)&~O_NONBLOCK); + fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL)&~O_NONBLOCK); +#endif + } + return soap->socket; + } + if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EAGAIN) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP accept failed in soap_accept()", SOAP_TCP_ERROR); + return -1; + } + } + } + else + { soap_set_receiver_error(soap, tcp_error(soap), "TCP no master socket in soap_accept()", SOAP_TCP_ERROR); + return -1; + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef MAC_CARBON +#ifndef PALM_1 +static int +tcp_disconnect(struct soap *soap) +{ +#ifdef WITH_OPENSSL + if (soap->ssl) + { int r, s = 0; + if (soap->session) + SSL_SESSION_free(soap->session); + if (*soap->host) + { soap->session = SSL_get1_session(soap->ssl); + if (soap->session) + { strcpy(soap->session_host, soap->host); + soap->session_port = soap->port; + } + } + r = SSL_shutdown(soap->ssl); + if (r != 1) + { s = ERR_get_error(); + if (s) + { if (soap_valid_socket(soap->socket)) + { shutdown((SOAP_SOCKET)soap->socket, 1); + soap->socket = SOAP_INVALID_SOCKET; + } + r = SSL_shutdown(soap->ssl); + } + } + DBGLOG(TEST, if (s) SOAP_MESSAGE(fdebug, "Shutdown failed: %d\n", SSL_get_error(soap->ssl, r))); + SSL_free(soap->ssl); + soap->ssl = NULL; + if (s) + return SOAP_SSL_ERROR; + ERR_remove_state(0); + } +#endif + if (soap_valid_socket(soap->socket)) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Closing socket %d\n", soap->socket)); + shutdown((SOAP_SOCKET)soap->socket, 2); + closesocket((SOAP_SOCKET)soap->socket); + soap->socket = SOAP_INVALID_SOCKET; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_closesock(struct soap *soap) +{ register int status = soap->error; +#ifndef MAC_CARBON + if (status == SOAP_EOF || !soap->keep_alive) + { if ((soap->error = soap->fclose(soap))) + return soap->error; + soap->socket = SOAP_INVALID_SOCKET; + } +#endif +#ifdef WITH_ZLIB + if (soap->zlib_state == SOAP_ZLIB_DEFLATE) + deflateEnd(&soap->d_stream); + else if (soap->zlib_state == SOAP_ZLIB_INFLATE) + inflateEnd(&soap->d_stream); + soap->zlib_state = SOAP_ZLIB_NONE; +#endif + return soap->error = status; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_hash(register const char *s) +{ register int h = 0; + while (*s) + h += *s++ & 0x1F; + return h % SOAP_IDHASH; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static void +soap_init_pht(struct soap *soap) +{ register int i; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing pointer hashtable\n")); + for (i = 0; i < SOAP_PTRHASH; i++) + soap->pht[i] = NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_new() +{ struct soap *soap = (struct soap*)SOAP_MALLOC(sizeof(struct soap)); + if (soap) + soap_init(soap); + return soap; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_new1(int mode) +{ return soap_new2(mode, mode); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_new2(int imode, int omode) +{ struct soap *soap = (struct soap*)SOAP_MALLOC(sizeof(struct soap)); + if (soap) + soap_init2(soap, imode, omode); + return soap; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +static void +soap_free_pht(struct soap *soap) +{ register struct soap_plist *pp, *next; + register int i; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free pointer hashtable\n")); + for (i = 0; i < SOAP_PTRHASH; i++) + { for (pp = soap->pht[i]; pp; pp = next) + { next = pp->next; + SOAP_FREE(pp); + } + soap->pht[i] = NULL; + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_embed_element(struct soap *soap, const void *p, const char *tag, int type) +{ register int i; + struct soap_plist *pp; + if (soap->version != 1) + soap->encoding = 1; + if ((i = soap_pointer_lookup(soap, p, type, &pp))) + { if (soap_is_embedded(soap, pp) || soap_is_single(soap, pp)) + return 0; + soap_set_embedded(soap, pp); + } + return i; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_embed_array(struct soap *soap, const void *p, const struct soap_array *a, int n, const char *tag, int type) +{ register int i; + struct soap_plist *pp; + if (soap->version != 1) + soap->encoding = 1; + if ((i = soap_array_pointer_lookup(soap, p, a, n, type, &pp))) + { if (soap_is_embedded(soap, pp) || soap_is_single(soap, pp)) + return 0; + soap_set_embedded(soap, pp); + } + return i; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_pointer_lookup(struct soap *soap, const void *p, int type, struct soap_plist **ppp) +{ register struct soap_plist *pp; + *ppp = NULL; + if (p) + for (pp = soap->pht[soap_hash_ptr(p)]; pp; pp = pp->next) + if (pp->ptr == p && pp->type == type) + { *ppp = pp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d id=%d\n", p, type, pp->id)); + return pp->id; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d: not found\n", p, type)); + return 0; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_array_pointer_lookup(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp) +{ struct soap_plist *pp; + *ppp = NULL; + if (!p || !a->__ptr) + return 0; + for (pp = soap->pht[soap_hash_ptr(a->__ptr)]; pp; pp = pp->next) + if (pp->type == type && pp->array && pp->array->__ptr == a->__ptr && pp->array->__size == n) + { *ppp = pp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d id=%d\n", a->__ptr, type, pp->id)); + return pp->id; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d: not found\n", a->__ptr, type)); + return 0; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_pointer_enter(struct soap *soap, const void *p, int type, struct soap_plist **ppp) +{ register struct soap_plist *pp; + if (!p) + { *ppp = NULL; + return 0; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enter location=%p type=%d id=%lu\n", p, type, soap->idnum+1)); + *ppp = pp = (struct soap_plist*)SOAP_MALLOC(sizeof(struct soap_plist)); + if (pp) + { register int h = soap_hash_ptr(p); + pp->next = soap->pht[h]; + pp->type = type; + if ((soap->mode & SOAP_XML_TREE) || soap->part == SOAP_IN_HEADER) + { pp->mark1 = 0; + pp->mark2 = 0; + } + else + { pp->mark1 = 1; + pp->mark2 = 1; + } + pp->ptr = p; + pp->array = NULL; + soap->pht[h] = pp; + return pp->id = ++soap->idnum; + } + return 0; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_array_pointer_enter(struct soap *soap, const void *p, const struct soap_array *a, int type, struct soap_plist **ppp) +{ struct soap_plist *pp; + *ppp = NULL; + if (!p || !a->__ptr) + return 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array enter location=%p size=%d type=%d id=%lu\n", a->__ptr, a->__size, type, soap->idnum+1)); + *ppp = pp = (struct soap_plist*)SOAP_MALLOC(sizeof(struct soap_plist)); + if (pp) + { register int h = soap_hash_ptr(a->__ptr); + pp->next = soap->pht[h]; + pp->type = type; + if ((soap->mode & SOAP_XML_TREE) || soap->part == SOAP_IN_HEADER) + { pp->mark1 = 0; + pp->mark2 = 0; + } + else + { pp->mark1 = 1; + pp->mark2 = 1; + } + pp->ptr = p; + pp->array = a; + soap->pht[h] = pp; + return pp->id = ++soap->idnum; + } + return 0; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_begin_count(struct soap *soap) +{ soap_clr_attr(soap); + soap_set_local_namespaces(soap); + if (soap->mode & SOAP_ENC_DIME) + soap->mode = soap->omode | SOAP_IO_LENGTH | SOAP_ENC_DIME; + else + { soap->mode = soap->omode; + if (((soap->mode & (SOAP_IO_STORE | SOAP_IO_CHUNK)) || (soap->mode & SOAP_ENC_XML)) && !soap->fprepare) + soap->mode &= ~SOAP_IO_LENGTH; + else + soap->mode |= SOAP_IO_LENGTH; + } + if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH) + { if (!(soap->mode & SOAP_ENC_DIME)) + soap->mode &= ~SOAP_IO_LENGTH; + if (soap->mode & SOAP_ENC_XML) + soap->mode |= SOAP_IO_BUFFER; + else + soap->mode |= SOAP_IO_STORE; + } + soap->count = 0; + soap->ns = 0; + soap->null = 0; + soap->position = 0; + soap->mustUnderstand = 0; + soap->encoding = 0; + soap->part = SOAP_BEGIN; + soap->idnum = 0; + soap->dime_count = 0; /* count # of attachments */ + soap->dime_size = 0; /* accumulate total size of attachments */ + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin count phase (socket=%d mode=%hd count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count)); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_begin_send(struct soap *soap) +{ soap_clr_attr(soap); + soap_set_local_namespaces(soap); + soap->mode = (soap->omode & ~SOAP_IO_LENGTH) | (soap->mode & SOAP_ENC_DIME); + if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH) + { if (soap->mode & SOAP_ENC_XML) + soap->mode |= SOAP_IO_BUFFER; + else + soap->mode |= SOAP_IO_STORE; + } + if ((soap->mode & SOAP_IO) == SOAP_IO_FLUSH && soap_valid_socket(soap->socket)) + { if (soap->count || (soap->mode & SOAP_ENC_XML)) + soap->mode |= SOAP_IO_BUFFER; + else + soap->mode |= SOAP_IO_STORE; + } + if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) + soap_new_block(soap); + if (!(soap->mode & SOAP_IO_KEEPALIVE)) + soap->keep_alive = 0; +#ifdef WIN32 +#ifndef UNDER_CE +#ifndef WITH_FASTCGI + if (!soap_valid_socket(soap->socket)) /* Set win32 stdout or soap->sendfd to BINARY, e.g. to support DIME */ +#ifdef __BORLANDC__ + setmode((SOAP_SOCKET)soap->sendfd, O_BINARY); +#else + _setmode((SOAP_SOCKET)soap->sendfd, _O_BINARY); +#endif +#endif +#endif +#endif + if (soap->mode & SOAP_IO) + { soap->bufidx = 0; + soap->buflen = 0; + } + soap->chunksize = 0; + soap->ns = 0; + soap->null = 0; + soap->position = 0; + soap->mustUnderstand = 0; + soap->encoding = 0; + soap->part = SOAP_BEGIN; + soap->idnum = 0; + soap->level = 0; +#ifdef WITH_ZLIB + soap->z_ratio_out = 1.0; + if ((soap->mode & SOAP_ENC_ZLIB) && soap->zlib_state != SOAP_ZLIB_DEFLATE) + { +#ifdef WITH_GZIP + memcpy(soap->z_buf, "\37\213\10\0\0\0\0\0\0\377", 10); + soap->d_stream.next_out = (Byte*)soap->z_buf + 10; + soap->d_stream.avail_out = SOAP_BUFLEN - 10; + soap->z_crc = crc32(0L, NULL, 0); + if (deflateInit2(&soap->d_stream, soap->z_level, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY) != Z_OK) +#else + soap->d_stream.next_out = (Byte*)soap->z_buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + if (deflateInit(&soap->d_stream, soap->z_level) != Z_OK) +#endif + return soap->error = SOAP_ZLIB_ERROR; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflate initialized\n")); + soap->zlib_state = SOAP_ZLIB_DEFLATE; + } +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin send phase (socket=%d mode=%hd count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count)); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_embedded(struct soap *soap, const void *p, int t) +{ struct soap_plist *pp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded %p type=%d\n", p, t)); + if (soap_pointer_lookup(soap, p, t, &pp)) + { pp->mark1 = 1; + pp->mark2 = 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded %p type=%d set to %d\n", p, t, (int)pp->mark1)); + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_reference(struct soap *soap, const void *p, int t) +{ register int i; + struct soap_plist *pp; + if (!p) + return 1; + i = soap_pointer_lookup(soap, p, t, &pp); + if (i) + { if (pp->mark1 == 0) + { pp->mark1 = 2; + pp->mark2 = 2; + } + } + else + { soap_pointer_enter(soap, p, t, &pp); + pp->mark1 = 0; + pp->mark2 = 0; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reference %p type = %d (%d %d)\n", p, t, (int)pp->mark1, (int)pp->mark2)); + return pp->mark1; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_array_reference(struct soap *soap, const void *p, const struct soap_array *a, int n, int t) +{ register int i; + struct soap_plist *pp; + if (!p) + return 1; + i = soap_array_pointer_lookup(soap, p, a, n, t, &pp); + if (i) + { if (pp->mark1 == 0) + { pp->mark1 = 2; + pp->mark2 = 2; + } + } + else if (!soap_array_pointer_enter(soap, p, a, t, &pp)) + return 1; + pp->mark1 = 0; + pp->mark2 = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array reference %p ptr=%p size=%d type = %d (%d %d)\n", p, a->__ptr, n, t, (int)pp->mark1, (int)pp->mark2)); + return pp->mark1; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_embedded_id(struct soap *soap, int id, const void *p, int t) +{ struct soap_plist *pp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id %p type=%d id=%d\n", p, t, id)); + if (soap->version == 1 && soap->encodingStyle && !(soap->mode & (SOAP_XML_TREE | SOAP_XML_GRAPH)) && soap->part != SOAP_IN_HEADER) + { if (id < 0) + { id = soap_pointer_lookup(soap, p, t, &pp); + if (id > 0 && pp) + { if (soap->mode & SOAP_IO_LENGTH) + pp->mark1 = 2; + else + pp->mark2 = 2; + } + return -1; + } + return id; + } + if (id < 0) + id = soap_pointer_lookup(soap, p, t, &pp); + else + soap_pointer_lookup(soap, p, t, &pp); + if (id > 0 && pp) + { if (soap->mode & SOAP_IO_LENGTH) + pp->mark1 = 1; + else + pp->mark2 = 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id id=%d %p type=%d = (%d %d)\n", id, p, t, (int)pp->mark1, (int)pp->mark2)); + } + return id; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_is_embedded(struct soap *soap, struct soap_plist *pp) +{ if (!pp) + return 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Is embedded? %d %d\n", (int)pp->mark1, (int)pp->mark2)); + if (soap->version == 1 && soap->encodingStyle && !(soap->mode & (SOAP_XML_TREE | SOAP_XML_GRAPH)) && soap->part != SOAP_IN_HEADER) + { if (soap->mode & SOAP_IO_LENGTH) + return pp->mark1 != 0; + return pp->mark2 != 0; + } + if (soap->mode & SOAP_IO_LENGTH) + return pp->mark1 == 1; + return pp->mark2 == 1; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_is_single(struct soap *soap, struct soap_plist *pp) +{ if ((soap->mode & SOAP_XML_TREE) || soap->part == SOAP_IN_HEADER) + return 1; + if (!pp) + return 0; + if (soap->mode & SOAP_IO_LENGTH) + return pp->mark1 == 0; + return pp->mark2 == 0; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_is_multi(struct soap *soap, struct soap_plist *pp) +{ if (soap->mode & SOAP_IO_LENGTH) + return pp->mark1 == 2; + return pp->mark2 == 2; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_embedded(struct soap *soap, struct soap_plist *pp) +{ if (!pp) + return; + if (soap->mode & SOAP_IO_LENGTH) + pp->mark1 = 1; + else + pp->mark2 = 1; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_attached(struct soap *soap, struct soap_plist *pp, const char *id, const char *type, const char *options, size_t size) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set attached id='%s' type='%s'\n", id?id:"", type?type:"")); + if (soap->mode & SOAP_IO_LENGTH) + { if (pp->mark1 != 3) + { pp->mark1 = 3; + soap->dime_count++; /* one more attachment found */ + soap->dime_size += 12; /* increase total size (DIME fields) */ + if (id) + soap->dime_size += (strlen(id)+3)&(~3); + if (type) + soap->dime_size += (strlen(type)+3)&(~3); + if (options) + soap->dime_size += 4 + (((((unsigned char)options[2] << 8 | (unsigned char)options[3]))+3)&(~3)); + soap->dime_size += (size+3)&(~3); + } + } + else if (pp->mark2 != 3) + pp->mark2 = 3; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static void +soap_init_iht(struct soap *soap) +{ register int i; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing ID hashtable\n")); + for (i = 0; i < SOAP_IDHASH; i++) + soap->iht[i] = NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +static void +soap_free_iht(struct soap *soap) +{ register int i; + register struct soap_ilist *ip, *p; + register struct soap_flist *fp, *q; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free ID hashtable\n")); + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = p) + { for (fp = ip->flist; fp; fp = q) + { q = fp->next; + SOAP_FREE(fp); + } + p = ip->next; + SOAP_FREE(ip); + } + soap->iht[i] = NULL; + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +static struct soap_ilist * +soap_hlookup(struct soap *soap, const char *id) +{ register struct soap_ilist *ip; + for (ip = soap->iht[soap_hash(id)]; ip; ip = ip->next) + if (!strcmp(ip->id, id)) + return ip; + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +struct soap_ilist * +SOAP_FMAC2 +soap_lookup(struct soap *soap, const char *id) +{ register struct soap_ilist *ip; + ip = soap_hlookup(soap, id); +#ifndef WITH_LEANER + if (!ip && *id != '#' && !strchr(id, ':')) /* try content id "cid:" with DIME attachments */ + { char cid[SOAP_TAGLEN]; + strcpy(cid, "cid:"); + strncat(cid + 4, id, sizeof(cid) - 5); + cid[sizeof(cid) - 1] = '\0'; + ip = soap_hlookup(soap, cid); + } +#endif + return ip; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +struct soap_ilist * +SOAP_FMAC2 +soap_enter(struct soap *soap, const char *id) +{ register int h; + register struct soap_ilist *ip; + ip = (struct soap_ilist*)SOAP_MALLOC(sizeof(struct soap_ilist) + strlen(id)); + if (ip) + { h = soap_hash(id); + strcpy(ip->id, id); + ip->next = soap->iht[h]; + soap->iht[h] = ip; + return ip; + } + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_malloc(struct soap *soap, size_t n) +{ register char *p; + if (!n) + return NULL; + if (!soap) + return SOAP_MALLOC(n); + n += (-(long)n) & 7; + if (!(p = (char*)SOAP_MALLOC(n + sizeof(void*) + sizeof(size_t)))) + { soap->error = SOAP_EOM; + return NULL; + } + /* keep chain of alloced cells for later destruction */ + soap->alloced = 1; + *(void**)(p + n) = soap->alist; + *(size_t*)(p + n + sizeof(void*)) = n; + soap->alist = p + n; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Malloc %u bytes at location %p\n", (unsigned int)n, p)); + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_dealloc(struct soap *soap, void *p) +{ if (!soap) + return; + if (p) + { register char **q; + for (q = (char**)&soap->alist; *q; q = *(char***)q) + { if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*)))) + { *q = **(char***)q; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Freed data at %p\n", p)); + SOAP_FREE(p); + return; + } + } + soap_delete(soap, p); + } + else + { register char *q; + while (soap->alist) + { q = (char*)soap->alist; + soap->alist = *(void**)q; + q -= *(size_t*)(q + sizeof(void*)); + if (q == (char*)soap->fault) + soap->fault = NULL; /* this was deallocated */ + else if (q == (char*)soap->header) + soap->header = NULL; /* this was deallocated */ + SOAP_FREE(q); + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Dealloc all data done\n")); + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_delete(struct soap *soap, void *p) +{ register struct soap_clist **cp = &soap->clist; + if (p) + { while (*cp) + { if (p == (*cp)->ptr) + { register struct soap_clist *q = *cp; + *cp = q->next; + q->fdelete(q); + SOAP_FREE(q); + return; + } + cp = &(*cp)->next; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: address not in list\n", p)); + } + else + { while (*cp) + { register struct soap_clist *q = *cp; + *cp = q->next; + if (q->ptr == (void*)soap->fault) + soap->fault = NULL; /* this was deallocated */ + else if (q->ptr == (void*)soap->header) + soap->header = NULL; /* this was deallocated */ + q->fdelete(q); + SOAP_FREE(q); + } + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +struct soap_clist * +SOAP_FMAC2 +soap_link(struct soap *soap, void *p, int t, int n, void (*fdelete)(struct soap_clist*)) +{ register struct soap_clist *cp; + if ((cp = (struct soap_clist*)SOAP_MALLOC(sizeof(struct soap_clist)))) + { cp->next = soap->clist; + cp->type = t; + cp->size = n; + cp->ptr = p; + cp->fdelete = fdelete; + soap->clist = cp; + } + return cp; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_unlink(struct soap *soap, const void *p) +{ register char **q; + register struct soap_clist **cp; + if (!soap || !p) + return; + for (q = (char**)&soap->alist; *q; q = *(char***)q) + { if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*)))) + { *q = **(char***)q; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked data %p\n", p)); + return; + } + } + for (cp = &soap->clist; *cp; cp = &(*cp)->next) + { if (p == (*cp)->ptr) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked class instance %p\n", p)); + q = (char**)*cp; + *cp = (*cp)->next; + SOAP_FREE(q); + return; + } + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_lookup_type(struct soap *soap, const char *id) +{ register struct soap_ilist *ip; + if (*id) + { ip = soap_lookup(soap, id); + if (ip) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup id='%s' type=%d\n", id, ip->type)); + return ip->type; + } + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "lookup type id='%s' NOT FOUND! Need to get it from xsi:type\n", id)); + return 0; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_id_lookup(struct soap *soap, const char *id, void **p, int t, size_t n, unsigned int k) +{ struct soap_ilist *ip; + void **q; + if (*id == '\0') + return p; + soap->alloced = 0; + if (!p) + p = (void**)soap_malloc(soap, sizeof(void*)); + ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */ + if (!ip) + { ip = soap_enter(soap, id); /* new hash table entry for string id */ + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding first href='%s' %p (%u bytes)\n", id, p, (unsigned int)n)); + ip->type = t; + ip->size = n; + ip->link = p; + ip->copy = NULL; + ip->flist = NULL; + ip->ptr = NULL; + ip->level = k; + *p = NULL; + } + else if (!soap->blist && ip->ptr) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolved href='%s' type='%d' (%u bytes)\n", id, t, (unsigned int)n)); + if (ip->type != t) + { soap->error = SOAP_HREF; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Object mismatch: id's type='%d' href's type='%d'\n", ip->type, t)); + return NULL; + } + while (ip->level < k) + { q = (void**)soap_malloc(soap, sizeof(void*)); + if (!q) + return NULL; + *p = (void*)q; + p = q; + k--; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); + } + *p = ip->ptr; + } + else if (ip->level > k) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving level %u pointers to href='%s'\n", ip->level, id)); + while (ip->level > k) + { void *s, **r = &ip->link; + q = (void**)ip->link; + while (q) + { *r = (void*)soap_malloc(soap, sizeof(void*)); + s = *q; + *q = *r; + r = *(void***)q; + q = (void**)s; + } + *r = NULL; + ip->size = n; + ip->copy = NULL; + ip->level = ip->level - 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); + } + q = (void**)ip->link; + ip->link = p; + *p = (void*)q; + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarded href='%s' (%u bytes)\n", id, (unsigned int)n)); + while (ip->level < k) + { q = (void**)soap_malloc(soap, sizeof(void*)); + *p = q; + p = q; + k--; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); + } + q = (void**)ip->link; + ip->link = p; + *p = (void*)q; + } + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_id_forward(struct soap *soap, const char *href, void *p, int t, size_t n) +{ struct soap_ilist *ip; + if (!p || !*href) + return p; + ip = soap_lookup(soap, soap->href); /* lookup pointer to hash table entry for string id */ + if (!ip) + { if (n >= sizeof(void*)) + { ip = soap_enter(soap, href); /* new hash table entry for string id */ + ip->type = t; + ip->size = n; + ip->link = NULL; + ip->copy = p; + ip->flist = NULL; + *(void**)p = NULL; + ip->ptr = NULL; + ip->level = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding first copying address %p for type %d href='%s'\n", p, t, href)); + return p; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding problem: copying location %p too small (%u) for href='%s'\n", p, (unsigned int)n, href)); + soap->error = SOAP_HREF; + return NULL; + } + else if (ip->ptr) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying value from location %p to location %p to resolve href='%s'\n", ip->ptr, p, href)); + memcpy(p, ip->ptr, n); + } + else if (n >= sizeof(void*)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding copying address %p for type %d href='%s' (prev in chain = %p)\n", p, t, href, ip->copy)); + *(void**)p = ip->copy; + ip->copy = p; + return p; + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding problem: copying location %p too small (%u) for href='%s'\n", p, (unsigned int)n, href)); + soap->error = SOAP_HREF; /* href to object too small to hold pointer */ + return NULL; + } + return ip->ptr; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_id_enter(struct soap *soap, const char *id, void *p, int t, size_t n, int k) +{ struct soap_ilist *ip; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Enter id='%s' type=%d loc=%p size=%d level=%d\n", id, t, p, (int)n, k)); + soap->alloced = 0; + if (*id == '\0') + { if (!p) + return soap_malloc(soap, n); + else + return p; + } + ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */ + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Lookup entry id='%s'\n", id)); + if (!ip) + { ip = soap_enter(soap, id); /* new hash table entry for string id */ + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "New entry id='%s' type=%d size=%u\n", id, t, (unsigned int)n)); + ip->type = t; + ip->size = n; + ip->link = NULL; + ip->copy = NULL; + ip->flist = NULL; + if (!p) + p = soap_malloc(soap, n); + ip->ptr = p; + ip->level = k; + } + else if (ip->ptr) /* storage address was forwarded */ + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Multiply defined id='%s'\n", id)); + if (p) + { soap->error = SOAP_MULTI_ID; + return NULL; + } + } + else + { if (!p) + p = soap_malloc(soap, n); + ip->ptr = p; + if (!soap->blist) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolve link chain to point to %p\n", ip->ptr)); + soap_resolve_ptr(ip); + } + } + return ip->ptr; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_end_send(struct soap *soap) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End send\n")); + if (soap->mode & SOAP_IO) /* need to flush the remaining data in buffer */ + { if (soap_flush(soap)) +#ifdef WITH_ZLIB + { if (soap->mode & SOAP_ENC_ZLIB && soap->zlib_state == SOAP_ZLIB_DEFLATE) + { soap->zlib_state = SOAP_ZLIB_NONE; + deflateEnd(&soap->d_stream); + } + return soap->error; + } +#else + return soap->error; +#endif +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { int r; + soap->d_stream.avail_in = 0; + do + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating remainder\n")); + r = deflate(&soap->d_stream, Z_FINISH); + if (soap->d_stream.avail_out != SOAP_BUFLEN) + { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN - soap->d_stream.avail_out)) + { soap->zlib_state = SOAP_ZLIB_NONE; + deflateEnd(&soap->d_stream); + return soap->error; + } + soap->d_stream.next_out = (Byte*)soap->z_buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + } + } while (r == Z_OK); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out)); + soap->z_ratio_out = (float)soap->d_stream.total_out / (float)soap->d_stream.total_in; + soap->mode &= ~SOAP_ENC_ZLIB; + soap->zlib_state = SOAP_ZLIB_NONE; + if (deflateEnd(&soap->d_stream) != Z_OK || r != Z_STREAM_END) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to end deflate: %s\n", soap->d_stream.msg?soap->d_stream.msg:"")); + return soap->error = SOAP_ZLIB_ERROR; + } +#ifdef WITH_GZIP + soap->z_buf[0] = soap->z_crc & 0xFF; + soap->z_buf[1] = (soap->z_crc >> 8) & 0xFF; + soap->z_buf[2] = (soap->z_crc >> 16) & 0xFF; + soap->z_buf[3] = (soap->z_crc >> 24) & 0xFF; + soap->z_buf[4] = soap->d_stream.total_in & 0xFF; + soap->z_buf[5] = (soap->d_stream.total_in >> 8) & 0xFF; + soap->z_buf[6] = (soap->d_stream.total_in >> 16) & 0xFF; + soap->z_buf[7] = (soap->d_stream.total_in >> 24) & 0xFF; + if (soap_flush_raw(soap, soap->z_buf, 8)) + return soap->error; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip crc32=%lu\n", soap->z_crc)); +#endif + } +#endif +#ifndef WITH_LEAN + if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) + { char *p; + if (!(soap->mode & SOAP_ENC_XML)) + { soap->mode--; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending buffered message of length %u\n", (unsigned int)soap->blist->size)); + if (soap->status >= SOAP_POST) + soap->error = soap->fpost(soap, soap->endpoint, soap->host, soap->port, soap->path, soap->action, soap->blist->size); + else if (soap->status != SOAP_STOP) + soap->error = soap->fresponse(soap, soap->status, soap->blist->size); + if (soap->error || soap_flush(soap)) + return soap->error; + soap->mode++; + } + for (p = soap_first_block(soap); p; p = soap_next_block(soap)) + { DBGMSG(SENT, p, soap_block_size(soap)); + if ((soap->error = soap->fsend(soap, p, soap_block_size(soap)))) + { soap_end_block(soap); + return soap->error; + } + } + soap_end_block(soap); + } + else if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) + { DBGMSG(SENT, "\r\n0\r\n\r\n", 7); + if ((soap->error = soap->fsend(soap, "\r\n0\r\n\r\n", 7))) + return soap->error; + } +#endif + } +#ifdef WITH_OPENSSL + if (!soap->ssl && soap_valid_socket(soap->socket) && !soap->keep_alive) + shutdown((SOAP_SOCKET)soap->socket, 1); /* Send TCP FIN */ +#else + if (soap_valid_socket(soap->socket) && !soap->keep_alive) + shutdown((SOAP_SOCKET)soap->socket, 1); /* Send TCP FIN */ +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of send message ok\n")); + soap->part = SOAP_END; + soap->count = 0; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_end_recv(struct soap *soap) +{ soap->part = SOAP_END; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "End of receive message ok\n")); +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { soap->mode &= ~SOAP_ENC_ZLIB; + memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN); + soap->bufidx = (char*)soap->d_stream.next_in - soap->z_buf; + soap->buflen = soap->z_buflen; + soap->zlib_state = SOAP_ZLIB_NONE; + if (inflateEnd(&soap->d_stream) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; +#ifdef WITH_GZIP + if (soap->zlib_in == SOAP_ZLIB_GZIP) + { wchar c; + short i; + for (i = 0; i < 8; i++) + { if ((int)(c = soap_getchar(soap)) == EOF) + return soap->error = SOAP_EOF; + soap->z_buf[i] = (char)c; + } + if (soap->z_crc != ((unsigned char)soap->z_buf[0] | (unsigned long)((unsigned char)soap->z_buf[1] << 8) | (unsigned long)((unsigned char)soap->z_buf[2] << 16) | (unsigned long)((unsigned char)soap->z_buf[3] << 24))) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: crc check failed, message corrupted? (crc32=%lu)\n", soap->z_crc)); + return soap->error = SOAP_ZLIB_ERROR; + } + if (soap->d_stream.total_out != ((unsigned char)soap->z_buf[4] | (unsigned long)((unsigned char)soap->z_buf[5] << 8) | (unsigned long)((unsigned char)soap->z_buf[6] << 16) | (unsigned long)((unsigned char)soap->z_buf[7] << 24))) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: incorrect message length\n")); + return soap->error = SOAP_ZLIB_ERROR; + } + } +#endif + } +#endif + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) + while ((int)soap_getchar(soap) != EOF) /* advance to last chunk */ + ; + if (soap->fdisconnect) + if ((soap->error = soap->fdisconnect(soap))) + return soap->error; + return soap_resolve(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_free(struct soap *soap) +{ register struct soap_nlist *np; + register struct soap_attribute *tp; + register struct Namespace *ns; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free namespace stack\n")); + while (soap->nlist) + { np = soap->nlist->next; + if (soap->nlist->ns) + SOAP_FREE(soap->nlist->ns); + SOAP_FREE(soap->nlist); + soap->nlist = np; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free any remaining temp blocks\n")); + while (soap->blist) + soap_end_block(soap); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attributes\n")); + while (soap->attributes) + { tp = soap->attributes->next; + if (soap->attributes->value) + SOAP_FREE(soap->attributes->value); + SOAP_FREE(soap->attributes); + soap->attributes = tp; + } + if (soap->labbuf) + SOAP_FREE(soap->labbuf); + soap->labbuf = NULL; + soap->lablen = 0; + soap->labidx = 0; + soap_free_pht(soap); + soap_free_iht(soap); + ns = soap->local_namespaces; + if (ns) + { for (; ns->id; ns++) + { if (ns->out) + { SOAP_FREE(ns->out); + if (soap->encodingStyle == ns->out) + soap->encodingStyle = SOAP_STR_EOS; + ns->out = NULL; + } + if (soap->encodingStyle == ns->ns) + soap->encodingStyle = SOAP_STR_EOS; + } + SOAP_FREE(soap->local_namespaces); + soap->local_namespaces = NULL; + } +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static void +soap_init_logs(struct soap *soap) +{ int i; + for (i = 0; i < SOAP_MAXLOGS; i++) + { soap->logfile[i] = NULL; + soap->fdebug[i] = NULL; + } +#ifdef SOAP_DEBUG + soap_set_recv_logfile(soap, "RECV.log"); + soap_set_sent_logfile(soap, "SENT.log"); + soap_set_test_logfile(soap, "TEST.log"); +#endif +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_open_logfile(struct soap *soap, int i) +{ if (soap->logfile[i]) + soap->fdebug[i] = fopen(soap->logfile[i], i < 2 ? "ab" : "a"); +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static void +soap_close_logfile(struct soap *soap, int i) +{ if (soap->fdebug[i]) + { fclose(soap->fdebug[i]); + soap->fdebug[i] = NULL; + } +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_close_logfiles(struct soap *soap) +{ int i; + for (i = 0; i < SOAP_MAXLOGS; i++) + soap_close_logfile(soap, i); +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static void +soap_set_logfile(struct soap *soap, int i, const char *logfile) +{ char *s = NULL; + soap_close_logfile(soap, i); + if (soap->logfile[i]) + SOAP_FREE((void*)soap->logfile[i]); + if (logfile) + if ((s = (char*)SOAP_MALLOC(strlen(logfile) + 1))) + strcpy(s, logfile); + soap->logfile[i] = s; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_recv_logfile(struct soap *soap, const char *logfile) +{ soap_set_logfile(soap, SOAP_INDEX_RECV, logfile); +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_sent_logfile(struct soap *soap, const char *logfile) +{ soap_set_logfile(soap, SOAP_INDEX_SENT, logfile); +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_test_logfile(struct soap *soap, const char *logfile) +{ soap_set_logfile(soap, SOAP_INDEX_TEST, logfile); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_copy(struct soap *soap) +{ return soap_copy_context((struct soap*)SOAP_MALLOC(sizeof(struct soap)), soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_copy_context(struct soap *copy, struct soap *soap) +{ if (copy) + { register struct soap_plugin *p; + memcpy(copy, soap, sizeof(struct soap)); + copy->copy = 1; + copy->user = NULL; + copy->userid = NULL; + copy->passwd = NULL; + copy->nlist = NULL; + copy->blist = NULL; + copy->clist = NULL; + copy->alist = NULL; + copy->attributes = NULL; + copy->local_namespaces = NULL; + soap_set_local_namespaces(copy); + soap_init_iht(copy); + soap_init_pht(copy); + copy->header = NULL; + copy->fault = NULL; + copy->action = NULL; + *copy->host = '\0'; +#ifndef WITH_LEAN +#ifdef WITH_COOKIES + copy->cookies = soap_copy_cookies(soap); +#else + copy->cookies = NULL; +#endif + soap_init_logs(copy); +#endif + copy->plugins = NULL; + for (p = soap->plugins; p; p = p->next) + { register struct soap_plugin *q = (struct soap_plugin*)SOAP_MALLOC(sizeof(struct soap_plugin)); + if (!q) + return NULL; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying plugin '%s'\n", p->id)); + *q = *p; + if (p->fcopy && (soap->error = p->fcopy(soap, q, p))) + { SOAP_FREE(q); + return NULL; + } + q->next = copy->plugins; + copy->plugins = q; + } + } + else + soap->error = SOAP_EOM; + return copy; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_init(struct soap *soap) +{ soap->version = 1; /* default SOAP 1.1 */ + soap_imode(soap, SOAP_IO_DEFAULT); + soap_omode(soap, SOAP_IO_DEFAULT); + soap->copy = 0; + soap->plugins = NULL; + soap->user = NULL; + soap->userid = NULL; + soap->passwd = NULL; + soap->fpost = http_post; + soap->fget = http_get; + soap->fposthdr = http_post_header; + soap->fresponse = http_response; + soap->fparse = http_parse; + soap->fparsehdr = http_parse_header; + soap->fconnect = NULL; + soap->fdisconnect = NULL; +#ifndef MAC_CARBON + soap->faccept = tcp_accept; + soap->fopen = tcp_connect; + soap->fclose = tcp_disconnect; + soap->fsend = fsend; + soap->frecv = frecv; +#endif + soap->fprepare = NULL; + soap->fignore = NULL; + soap->fplugin = fplugin; + soap->fdimereadopen = NULL; + soap->fdimewriteopen = NULL; + soap->fdimereadclose = NULL; + soap->fdimewriteclose = NULL; + soap->fdimeread = NULL; + soap->fdimewrite = NULL; + soap->float_format = "%.8g"; /* .8 preserves single FP precision as much as possible, but might not be very efficient */ + soap->double_format = "%.17lg"; /* .17 preserves double FP precision as much as possible, but might not be very efficient */ + soap->dime_id_format = "cid:id%d"; /* default DIME id format */ + soap->http_version = "1.1"; + soap->encodingStyle = SOAP_STR_EOS; + soap->actor = NULL; + soap->max_keep_alive = SOAP_MAXKEEPALIVE; + soap->keep_alive = 0; + soap->recv_timeout = 0; + soap->send_timeout = 0; + soap->connect_timeout = 0; + soap->accept_timeout = 0; + soap->socket_flags = 0; + soap->connect_flags = 0; + soap->bind_flags = 0; + soap->accept_flags = 0; + soap->ip = 0; + soap->labbuf = NULL; + soap->lablen = 0; + soap->labidx = 0; +#ifndef WITH_NONAMESPACES + soap->namespaces = namespaces; +#else + soap->namespaces = NULL; +#endif + soap->local_namespaces = NULL; + soap->nlist = NULL; + soap->blist = NULL; + soap->clist = NULL; + soap->alist = NULL; + soap->attributes = NULL; + soap->header = NULL; + soap->fault = NULL; + soap->master = SOAP_INVALID_SOCKET; + soap->socket = SOAP_INVALID_SOCKET; + soap->os = NULL; + soap->is = NULL; + soap->dom = NULL; +#ifndef UNDER_CE + soap->recvfd = 0; + soap->sendfd = 1; +#else + soap->recvfd = stdin; + soap->sendfd = stdout; +#endif + soap->host[0] = '\0'; + soap->port = 0; + soap->action = NULL; + soap->proxy_host = NULL; + soap->proxy_port = 8080; + soap->proxy_userid = NULL; + soap->proxy_passwd = NULL; +#ifdef WITH_OPENSSL + soap->fsslauth = ssl_auth_init; + soap->fsslverify = ssl_verify_callback; + soap->bio = NULL; + soap->ssl = NULL; + soap->ctx = NULL; + soap->require_server_auth = 0; + soap->require_client_auth = 0; + soap->rsa = 0; + soap->keyfile = NULL; + soap->password = NULL; + soap->dhfile = NULL; + soap->cafile = NULL; + soap->capath = NULL; + soap->randfile = NULL; + soap->session = NULL; +#endif +#ifdef WITH_ZLIB + soap->zlib_state = SOAP_ZLIB_NONE; + soap->zlib_in = SOAP_ZLIB_NONE; + soap->zlib_out = SOAP_ZLIB_NONE; + soap->d_stream.zalloc = NULL; + soap->d_stream.zfree = NULL; + soap->d_stream.opaque = NULL; + soap->z_level = 6; +#endif +#ifndef WITH_LEAN + soap->cookies = NULL; + soap->cookie_domain = NULL; + soap->cookie_path = NULL; + soap->cookie_max = 32; + soap_init_logs(soap); +#endif +/* WR[ */ +#ifdef WMW_RPM_IO + soap->rpmreqid = NULL; +#endif /* WMW_RPM_IO */ +/* ]WR */ + soap_init_iht(soap); + soap_init_pht(soap); + soap_begin(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_init1(struct soap *soap, int mode) +{ soap_init2(soap, mode, mode); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_init2(struct soap *soap, int imode, int omode) +{ soap_init(soap); + soap_imode(soap, imode); + soap_omode(soap, omode); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_begin(struct soap *soap) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing\n")); + if (!soap->keep_alive) + { soap->buflen = 0; + soap->bufidx = 0; + } + soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0); + soap->null = 0; + soap->position = 0; + soap->encoding = 0; + soap->mustUnderstand = 0; + soap->mode = 0; + soap->ns = 0; + soap->part = SOAP_BEGIN; + soap->alloced = 0; + soap->count = 0; + soap->length = 0; + soap->cdata = 0; + soap->error = SOAP_OK; + soap->peeked = 0; + soap->ahead = 0; + soap->idnum = 0; + soap->level = 0; + soap->endpoint[0] = '\0'; + soap->dime_chunksize = 0; + soap->dime_buflen = 0; + soap->dot_net_bug = 0; + soap_free(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_end(struct soap *soap) +{ register struct soap_clist *cp; + soap_free(soap); + soap_dealloc(soap, NULL); + while (soap->clist) + { cp = soap->clist->next; + SOAP_FREE(soap->clist); + soap->clist = cp; + } + soap_closesock(soap); +#ifndef WITH_LEAN + soap_close_logfiles(soap); +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_namespaces(struct soap *soap, struct Namespace *p) +{ struct Namespace *ns = soap->local_namespaces; + struct soap_nlist *np, *nq, *nr; + unsigned int level = soap->level; + soap->namespaces = p; + soap->local_namespaces = NULL; + soap_set_local_namespaces(soap); + /* reverse the list */ + np = soap->nlist; + soap->nlist = NULL; + if (np) + { nq = np->next; + np->next = NULL; + while (nq) + { nr = nq->next; + nq->next = np; + np = nq; + nq = nr; + } + } + while (np) + { soap->level = np->level; /* preserve element nesting level */ + if (np->ns) + { if (soap_push_namespace(soap, np->id, np->ns)) + return soap->error; + } + else if (np->index >= 0 && ns) + { if (ns[np->index].out) + { if (soap_push_namespace(soap, np->id, ns[np->index].out)) + return soap->error; + } + else if (soap_push_namespace(soap, np->id, ns[np->index].ns)) + return soap->error; + } + if (np->ns) + SOAP_FREE(np->ns); + nq = np; + np = np->next; + SOAP_FREE(nq); + } + if (ns) + { int i; + for (i = 0; ns[i].id; i++) + { if (ns[i].out) + { SOAP_FREE(ns[i].out); + ns[i].out = NULL; + } + } + SOAP_FREE(ns); + } + soap->level = level; /* restore level */ + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +static void +soap_set_local_namespaces(struct soap *soap) +{ if (soap->namespaces && !soap->local_namespaces) + { register struct Namespace *ns; + register size_t n = 1; + for (ns = soap->namespaces; ns->id; ns++) + n++; + if (n > 3) + { n *= sizeof(struct Namespace); + ns = (struct Namespace*)SOAP_MALLOC(n); + if (ns) + { memcpy(ns, soap->namespaces, n); + ns[0].id = "SOAP-ENV"; + ns[1].id = "SOAP-ENC"; + ns[2].id = "xsi"; + if (ns[0].ns) + { if (!strcmp(ns[0].ns, soap_env1)) + soap->version = 1; + else + soap->version = 2; + } + soap->local_namespaces = ns; + } + } + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element(struct soap *soap, const char *tag, int id, const char *type) +{ struct Namespace *ns = soap->local_namespaces; + register const char *s; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element begin tag='%s' id='%d' type='%s'\n", tag, id, type?type:"")); +/**/ +#ifdef WITH_DOM + if (soap->mode & SOAP_XML_DOM) + { register struct soap_dom_element *p, *e = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element)); + e->next = NULL; + e->prnt = soap->dom; + e->nstr = NULL; + e->name = soap_strdup(soap, tag); /* check EOM? */ + e->data = NULL; + e->type = 0; + e->node = NULL; + e->elts = NULL; + e->atts = NULL; + if (soap->dom) + { p = soap->dom->elts; + if (p) + { while (p->next) + p = p->next; + p->next = e; + } + else + soap->dom->elts = e; + } + soap->dom = e; + } + else +#endif +{ + soap->level++; + if (!soap->ns && !(soap->mode & SOAP_XML_CANONICAL)) + if (soap_send(soap, "")) + return soap->error; + if (soap_send_raw(soap, "<", 1)) + return soap->error; + s = tag; + if (ns && soap->part != SOAP_IN_ENVELOPE && (soap->part == SOAP_IN_HEADER || !soap->encodingStyle)) + { register const char *t = strchr(s, ':'); + if (t) + { s = t + 1; + for (ns++; ns->id; ns++) + { if ((ns->out || ns->ns) && !strncmp(ns->id, tag, t - tag) && !ns->id[t - tag]) + { if (soap_send(soap, s) || soap_attribute(soap, "xmlns", ns->out ? ns->out : ns->ns)) + return soap->error; + s = NULL; + break; + } + } + } + } + if (s) + if (soap_send(soap, tag)) + return soap->error; +} +/**/ + if (!soap->ns) + { for (ns = soap->local_namespaces; ns && ns->id; ns++) + { if (*ns->id && (ns->out || ns->ns)) + { sprintf(soap->tmpbuf, "xmlns:%s", ns->id); + if (soap_attribute(soap, soap->tmpbuf, ns->out ? ns->out : ns->ns)) + return soap->error; + } + } + soap->ns = 1; + } + if (id > 0) + { sprintf(soap->tmpbuf, "_%d", id); + if (soap_attribute(soap, "id", soap->tmpbuf)) + return soap->error; + } + if (type && *type) + { if (soap_attribute(soap, "xsi:type", type)) + return soap->error; + } + if (soap->null && soap->position > 0) + { int i; + sprintf(soap->tmpbuf, "[%d", soap->positions[0]); + for (i = 1; i < soap->position; i++) + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), ",%d", soap->positions[i]); + strcat(soap->tmpbuf, "]"); + if (soap_attribute(soap, "SOAP-ENC:position", soap->tmpbuf)) + return soap->error; + } + if (soap->mustUnderstand) + { if (soap->actor && *soap->actor) + { if (soap_attribute(soap, soap->version == 2 ? "SOAP-ENV:role" : "SOAP-ENV:actor", soap->actor)) + return soap->error; + } + if (soap_attribute(soap, "SOAP-ENV:mustUnderstand", soap->version == 2 ? "true" : "1")) + return soap->error; + soap->mustUnderstand = 0; + } + if (soap->encoding) + { if (soap->encodingStyle) + { if (!*soap->encodingStyle && soap->local_namespaces) + { if (soap->local_namespaces[1].out) + soap->encodingStyle = soap->local_namespaces[1].out; + else + soap->encodingStyle = soap->local_namespaces[1].ns; + } + if (soap_attribute(soap, "SOAP-ENV:encodingStyle", soap->encodingStyle)) + return soap->error; + } + soap->encoding = 0; + } + soap->null = 0; + soap->position = 0; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_begin_out(struct soap *soap, const char *tag, int id, const char *type) +{ if (*tag == '-') + return SOAP_OK; + if (soap_element(soap, tag, id, type)) + return soap->error; + return soap_element_start_end_out(soap, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +#ifndef HAVE_STRRCHR +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_strrchr(const char *s, int t) +{ register char *r = NULL; + while (*s) + if (*s++ == t) + r = (char*)s - 1; + return r; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +#ifndef HAVE_STRTOL +SOAP_FMAC1 +long +SOAP_FMAC2 +soap_strtol(const char *s, char **t, int b) +{ register long n = 0; + register int c; + while (*s > 0 && *s <= 32) + s++; + if (b == 10) + { short neg = 0; + if (*s == '-') + { s++; + neg = 1; + } + else if (*s == '+') + s++; + while ((c = *s) && c >= '0' && c <= '9') + { if (n > 214748364) + break; + n *= 10; + n += c - '0'; + s++; + } + if (neg) + n = -n; + } + else /* b == 16 and value is always positive */ + { while ((c = *s)) + { if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'F') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'f') + c -= 'a' - 10; + if (n > 0x07FFFFFF) + break; + n <<= 4; + n += c; + s++; + } + } + if (t) + *t = (char*)s; + return n; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +#ifndef HAVE_STRTOUL +SOAP_FMAC1 +unsigned long +SOAP_FMAC2 +soap_strtoul(const char *s, char **t, int b) +{ unsigned long n = 0; + register int c; + while (*s > 0 && *s <= 32) + s++; + if (b == 10) + { if (*s == '+') + s++; + while ((c = *s) && c >= '0' && c <= '9') + { if (n > 429496729) + break; + n *= 10; + n += c - '0'; + s++; + } + } + else /* b == 16 */ + { while ((c = *s)) + { if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'F') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'f') + c -= 'a' - 10; + if (n > 0x0FFFFFFF) + break; + n <<= 4; + n += c; + s++; + } + } + if (t) + *t = (char*)s; + return n; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_array_begin_out(struct soap *soap, const char *tag, int id, const char *type, const char *offset) +{ if (soap_element(soap, tag, id, "SOAP-ENC:Array")) + return soap->error; + if (soap->version == 2) + { const char *s; + s = soap_strrchr(type, '['); + if ((size_t)(s - type) < sizeof(soap->tmpbuf)) + { strncpy(soap->tmpbuf, type, s - type); + soap->tmpbuf[s - type] = '\0'; + if (type && *type && (soap_attribute(soap, "SOAP-ENC:itemType", soap->tmpbuf))) + return soap->error; + if (s && (soap_attribute(soap, "SOAP-ENC:arraySize", s + 1))) + return soap->error; + } + } + else + { if (offset && (soap_attribute(soap, "SOAP-ENC:offset", offset))) + return soap->error; + if (type && *type && (soap_attribute(soap, "SOAP-ENC:arrayType", type))) + return soap->error; + } + return soap_element_start_end_out(soap, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_start_end_out(struct soap *soap, const char *tag) +{ register struct soap_attribute *tp; +/**/ +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible) + { register struct soap_dom_attribute *a = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); + a->next = soap->dom->atts; + a->nstr = NULL; + a->name = soap_strdup(soap, tp->name); /* check EOM */ + a->data = soap_strdup(soap, tp->value); /* check EOM */ + a->wide = NULL; + soap->dom->atts = a; + tp->visible = 0; + } + } + return SOAP_OK; + } +#endif +/**/ + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible) + { if (soap_send_raw(soap, " ", 1) + || soap_send(soap, tp->name)) + return soap->error; + if (tp->visible == 2 && tp->value) + if (soap_send_raw(soap, "=\"", 2) + || soap_string_out(soap, tp->value, 1) + || soap_send_raw(soap, "\"", 1)) + return soap->error; + tp->visible = 0; + } + } + if (tag) + { soap->level--; +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { if (soap_send_raw(soap, ">", 1) + || soap_element_end_out(soap, tag)) + return soap->error; + return SOAP_OK; + } +#endif + return soap_send_raw(soap, "/>", 2); + } + return soap_send_raw(soap, ">", 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_end_out(struct soap *soap, const char *tag) +{ if (*tag == '-') + return SOAP_OK; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element ending tag='%s'\n", tag)); +/**/ +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { if (soap->dom->prnt) + soap->dom = soap->dom->prnt; + return SOAP_OK; + } +#endif +/**/ + if (soap->part != SOAP_IN_ENVELOPE && (soap->part == SOAP_IN_HEADER || !soap->encodingStyle) && soap->local_namespaces) + { const char *s = strchr(tag, ':'); + if (s && strncmp(tag, "SOAP-ENV", s - tag)) + tag = s + 1; + } + soap->level--; + if (soap_send_raw(soap, "", 1)) + return soap->error; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_ref(struct soap *soap, const char *tag, int id, int href) +{ int n = 0; + if (soap_element(soap, tag, id, NULL)) + return soap->error; + if (soap->version == 2) + n = 1; + sprintf(soap->tmpbuf, "#_%d", href); + if (soap_attribute(soap, "href" + n, soap->tmpbuf + n) + || soap_element_start_end_out(soap, tag)) + return soap->error; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_href(struct soap *soap, const char *tag, int id, const char *href) +{ if (soap_element(soap, tag, id, NULL) + || soap_attribute(soap, "href", href) + || soap_element_start_end_out(soap, tag)) + return soap->error; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_null(struct soap *soap, const char *tag, int id, const char *type) +{ struct soap_attribute *tp; + for (tp = soap->attributes; tp; tp = tp->next) + if (tp->visible) + break; + if (tp || (soap->version == 2 && soap->position > 0) || id > 0 || (soap->mode & SOAP_XML_NIL)) + { if (soap_element(soap, tag, id, type)) + return soap->error; + if (soap->part != SOAP_IN_HEADER && soap->encodingStyle) + if (soap_attribute(soap, "xsi:nil", "true")) + return soap->error; + return soap_element_start_end_out(soap, tag); + } + soap->null = 1; + soap->position = 0; + soap->mustUnderstand = 0; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_result(struct soap *soap, const char *tag) +{ if (soap->version == 2 && soap->encodingStyle) + if (soap_element(soap, "SOAP-RPC:result", 0, NULL) + || soap_attribute(soap, "xmlns:SOAP-RPC", soap_rpc) + || soap_element_start_end_out(soap, NULL) + || soap_string_out(soap, tag, 0) + || soap_element_end_out(soap, "SOAP-RPC:result")) + return soap->error; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_attribute(struct soap *soap, const char *name, const char *value) +{ +/**/ +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { register struct soap_dom_attribute *a = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); + a->next = soap->dom->atts; + a->nstr = NULL; + a->name = soap_strdup(soap, name); /* check EOM */ + a->data = soap_strdup(soap, value); /* check EOM */ + a->wide = NULL; + soap->dom->atts = a; + return SOAP_OK; + } +#endif +/**/ +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { if (soap_set_attr(soap, name, value)) + return soap->error; + } + else +#endif + { if (soap_send_raw(soap, " ", 1) + || soap_send(soap, name)) + return soap->error; + if (value) + if (soap_send_raw(soap, "=\"", 2) + || soap_string_out(soap, value, 1) + || soap_send_raw(soap, "\"", 1)) + return soap->error; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_begin_in(struct soap *soap, const char *tag) +{ if (tag && *tag == '-') + return SOAP_OK; + if (!soap_peek_element(soap)) + { if (soap->other) + return soap->error = SOAP_TAG_MISMATCH; + if (!(soap->error = soap_match_tag(soap, soap->tag, tag))) + { if (tag && !soap->encodingStyle) + { const char *s = strchr(tag, ':'); + if (s) + soap_push_default_namespace(soap, tag, s - tag); + } + soap->peeked = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:"" )); + if (soap->body) + soap->level++; + } + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_end_in(struct soap *soap, const char *tag) +{ register wchar c; + register char *s; + register const char *t; + if (tag && *tag == '-') + return SOAP_OK; + soap->level--; + soap_pop_namespace(soap); + if (soap->peeked) + { if (*soap->tag == '\0') + { soap->peeked = 0; + soap->error = SOAP_OK; + } + else + return soap->error = SOAP_SYNTAX_ERROR; + } + else + { while (((c = soap_get(soap)) != TT)) + { if ((int)c == EOF) + return soap->error = SOAP_EOF; + if (c == LT) + return soap->error = SOAP_SYNTAX_ERROR; + } + } + s = soap->tag; + do c = soap_get(soap); + while (soap_blank(c)); + do + { *s++ = (char)c; + c = soap_get(soap); + } while (soap_notblank(c)); + *s = '\0'; + if ((int)c == EOF) + return soap->error = SOAP_EOF; + while (soap_blank(c)) + c = soap_get(soap); + if (c != GT) + return soap->error = SOAP_SYNTAX_ERROR; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:"")); + if (!tag) + return SOAP_OK; + if ((s = strchr(soap->tag, ':'))) + s++; + else + s = soap->tag; + if ((t = strchr(tag, ':'))) + t++; + else + t = tag; + if (!SOAP_STRCMP(s, t)) + return SOAP_OK; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element does not match\n")); + return soap->error = SOAP_SYNTAX_ERROR; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +struct soap_attribute * +SOAP_FMAC2 +soap_attr(struct soap *soap, const char *name) +{ register struct soap_attribute *tp; + for (tp = soap->attributes; tp; tp = tp->next) + if (!soap_match_tag(soap, tp->name, name)) + return tp; + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char * +SOAP_FMAC2 +soap_attr_value(struct soap *soap, const char *name) +{ register struct soap_attribute *tp = soap_attr(soap, name); + if (tp && tp->visible == 2) + return tp->value; + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_attr(struct soap *soap, const char *name, const char *value) +{ register struct soap_attribute *tp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set attribute %s='%s'\n", name, value?value:"")); + for (tp = soap->attributes; tp; tp = tp->next) + if (!strcmp(tp->name, name)) + break; + if (!tp) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute %s\n", name)); + if (!(tp = (struct soap_attribute*)SOAP_MALLOC(sizeof(struct soap_attribute) + strlen(name)))) + return soap->error = SOAP_EOM; + tp->ns = NULL; +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { struct soap_attribute **tpp = &soap->attributes; + const char *s = strchr(name, ':'); + if (!strncmp(name, "xmlns", 5)) + { for (; *tpp; tpp = &(*tpp)->next) + if (strncmp((*tpp)->name, "xmlns", 5) || strcmp((*tpp)->name + 5, name + 5) > 0) + break; + } + else if (!s) + { for (; *tpp; tpp = &(*tpp)->next) + if (strncmp((*tpp)->name, "xmlns", 5) && ((*tpp)->ns || strcmp((*tpp)->name, name) > 0)) + break; + } + else + { int k; + for (; *tpp; tpp = &(*tpp)->next) + { if (!strncmp((*tpp)->name, "xmlns:", 6) && !strncmp((*tpp)->name + 6, name, s - name) && !(*tpp)->name[6 + s - name]) + { if (!tp->ns) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Canonicalization: prefix %s=%p(%s)\n", name, (*tpp)->ns, (*tpp)->ns)); + tp->ns = (*tpp)->ns; + } + } + else if (strncmp((*tpp)->name, "xmlns", 5) && (*tpp)->ns && tp->ns && ((k = strcmp((*tpp)->ns, tp->ns)) > 0 || (!k && strcmp((*tpp)->name, name) > 0))) + break; + } + } + tp->next = *tpp; + *tpp = tp; + } + else +#endif + { tp->next = soap->attributes; + soap->attributes = tp; + } + strcpy(tp->name, name); + tp->value = NULL; + } + else if (value && tp->value && tp->size <= strlen(value)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute value of %s (free %p)\n", name, tp->value)); + SOAP_FREE(tp->value); + tp->value = NULL; + tp->ns = NULL; + } + if (value) + { if (!tp->value) + { tp->size = strlen(value) + 1; + if (!(tp->value = (char*)SOAP_MALLOC(tp->size))) + return soap->error = SOAP_EOM; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute value of %s (%p)\n", tp->name, tp->value)); + } + strcpy(tp->value, value); + if (!strncmp(tp->name, "xmlns:", 6)) + tp->ns = tp->value; + tp->visible = 2; + } + else + tp->visible = 1; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_clr_attr(struct soap *soap) +{ register struct soap_attribute *tp; +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { while (soap->attributes) + { tp = soap->attributes->next; + SOAP_FREE(soap->attributes->value); + SOAP_FREE(soap->attributes); + soap->attributes = tp; + } + } + else +#endif + { for (tp = soap->attributes; tp; tp = tp->next) + tp->visible = 0; + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +static int +soap_getattrval(struct soap *soap, char *s, size_t n, wchar d) +{ size_t i; + wchar c; + for (i = 0; i < n; i++) + { c = soap_getutf8(soap); + switch (c) + { + case TT: + *s++ = '<'; + soap_unget(soap, '/'); + break; + case LT: + *s++ = '<'; + break; + case GT: + if (d == ' ') + { soap_unget(soap, c); + *s = '\0'; + return SOAP_OK; + } + *s++ = '>'; + break; + case QT: + if (c == d) + { *s = '\0'; + return SOAP_OK; + } + *s++ = '"'; + break; + case AP: + if (c == d) + { *s = '\0'; + return SOAP_OK; + } + *s++ = '\''; + break; + case '\t': + case '\n': + case '\r': + case ' ': + case '/': + if (d == ' ') + { soap_unget(soap, c); + *s = '\0'; + return SOAP_OK; + } + default: + if ((int)c == EOF) + return soap->error = SOAP_EOF; + *s++ = (char)c; + } + } + return soap->error = SOAP_EOM; +} +#endif + +/******************************************************************************/ +#ifdef WITH_FAST +#ifndef PALM_2 +static int +soap_append_lab(struct soap *soap, const char *s, size_t n) +{ if (soap->labidx + n >= soap->lablen) + { register char *t = soap->labbuf; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enlarging look-aside buffer to append data, old size=%lu", (unsigned long)soap->lablen)); + if (soap->lablen == 0) + soap->lablen = SOAP_LABLEN; + while (soap->labidx + n >= soap->lablen) + soap->lablen <<= 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, ", new size=%lu\n", (unsigned long)soap->lablen)); + soap->labbuf = (char*)SOAP_MALLOC(soap->lablen); + if (!soap->labbuf) + { if (t) + free(t); + return soap->error = SOAP_EOM; + } + if (t && soap->labidx) + { memcpy(soap->labbuf, t, soap->labidx); + free(t); + } + } + if (s) + { memcpy(soap->labbuf + soap->labidx, s, n); + soap->labidx += n; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_peek_element(struct soap *soap) +{ struct soap_attribute *tp; + const char *t; + register char *s; + register wchar c; + register int i; + if (soap->peeked) + { if (*soap->tag == '\0') + return soap->error = SOAP_NO_TAG; + return SOAP_OK; + } + soap->peeked = 1; + for (;;) + { while (((c = soap_get(soap)) != LT) && c != TT) + { if ((int)c == EOF) + return soap->error = SOAP_EOF; + } + if (c == TT) + { *soap->tag = '\0'; + return soap->error = SOAP_NO_TAG; /* ending tag found */ + } + s = soap->tag; + do c = soap_get(soap); + while (soap_blank(c)); + i = sizeof(soap->tag); + while (c != '/' && soap_notblank(c)) + { if (--i > 0) + *s++ = (char)c; + c = soap_get(soap); + } + while (soap_blank(c)) + c = soap_get(soap); + *s = '\0'; + if (*soap->tag != '?') + break; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "XML PI <%s?>\n", soap->tag)); + while ((int)c != EOF && c != GT && c != '?') + { s = soap->tmpbuf; + i = sizeof(soap->tmpbuf) - 2; + while (c != '=' && c != GT && c != '?' && soap_notblank(c)) + { if (--i > 0) + *s++ = (char)c; + c = soap_get(soap); + } + while (soap_blank(c)) + c = soap_get(soap); + if (c == '=') + { *s++ = '='; + do c = soap_get(soap); + while (soap_blank(c)); + if (c != QT && c != AP) + { soap_unget(soap, c); + c = ' '; /* blank delimiter */ + } + if (soap_getattrval(soap, s, i, c) == SOAP_EOM) + while (soap_getattrval(soap, soap->tmpbuf, sizeof(soap->tmpbuf), c) == SOAP_EOM) + ; + else if (!strcmp(soap->tag, "?xml") && (!soap_tag_cmp(soap->tmpbuf, "encoding=iso-8859-1") || !soap_tag_cmp(soap->tmpbuf, "encoding=latin1"))) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "XML latin1 encoding\n")); + soap->mode |= SOAP_C_LATIN; + } + } + do c = soap_get(soap); + while (soap_blank(c)); + } + } + soap->id[0] = '\0'; + soap->href[0] = '\0'; + soap->type[0] = '\0'; + soap->arrayType[0] = '\0'; + soap->arraySize[0] = '\0'; + soap->arrayOffset[0] = '\0'; + soap->other = 0; + soap->root = -1; + soap->position = 0; + soap->null = 0; + soap->mustUnderstand = 0; + soap_clr_attr(soap); + soap_pop_namespace(soap); + while ((int)c != EOF && c != GT && c != '/') + { s = soap->tmpbuf; + i = sizeof(soap->tmpbuf); + while (c != '=' && c != '/' && soap_notblank(c)) + { if (--i > 0) + *s++ = (char)c; + c = soap_get(soap); + } + *s = '\0'; + if (i == sizeof(soap->tmpbuf)) + return soap->error = SOAP_SYNTAX_ERROR; + if (!strncmp(soap->tmpbuf, "xmlns:", 6)) + { soap->tmpbuf[5] = '\0'; + t = soap->tmpbuf + 6; + } + else if (!strcmp(soap->tmpbuf, "xmlns")) + t = SOAP_STR_EOS; + else + t = NULL; + tp = soap_attr(soap, soap->tmpbuf); + if (!tp) + { tp = (struct soap_attribute*)SOAP_MALLOC(sizeof(struct soap_attribute) + strlen(soap->tmpbuf)); + if (!tp) + return soap->error = SOAP_EOM; + strcpy(tp->name, soap->tmpbuf); + tp->value = NULL; + tp->size = 0; + tp->next = soap->attributes; + soap->attributes = tp; + } + while (soap_blank(c)) + c = soap_get(soap); + if (c == '=') + { do c = soap_get(soap); + while (soap_blank(c)); + if (c != QT && c != AP) + { soap_unget(soap, c); + c = ' '; /* blank delimiter */ + } + if (soap_getattrval(soap, tp->value, tp->size, c)) + { +#ifdef WITH_FAST + if (soap->error != SOAP_EOM) + return soap->error; + soap->error = SOAP_OK; + soap->labidx = 0; + if (soap_append_lab(soap, tp->value, tp->size)) + return soap->error; + SOAP_FREE(tp->value); + for (;;) + { if (soap_getattrval(soap, soap->labbuf + soap->labidx, soap->lablen - soap->labidx, c)) + { if (soap->error != SOAP_EOM) + return soap->error; + soap->error = SOAP_OK; + soap->labidx = soap->lablen; + if (soap_append_lab(soap, NULL, 0)) + return soap->error; + } + else + break; + } + tp->size = soap->lablen; + if (!(tp->value = (char*)SOAP_MALLOC(tp->size))) + return soap->error = SOAP_EOM; + memcpy(tp->value, soap->labbuf, soap->lablen); +#else + size_t n; + if (soap->error != SOAP_EOM) + return soap->error; + soap->error = SOAP_OK; + if (soap_new_block(soap)) + return soap->error; + for (;;) + { if (!(s = (char*)soap_push_block(soap, SOAP_BLKLEN))) + return soap->error; + if (soap_getattrval(soap, s, SOAP_BLKLEN, c)) + { if (soap->error != SOAP_EOM) + return soap->error; + soap->error = SOAP_OK; + } + else + break; + } + n = tp->size + soap->blist->size; + if (!(s = (char*)SOAP_MALLOC(n))) + return soap->error = SOAP_EOM; + if (tp->value) + { memcpy(s, tp->value, tp->size); + SOAP_FREE(tp->value); + } + soap_save_block(soap, s + tp->size); + tp->value = s; + tp->size = n; +#endif + } + do c = soap_get(soap); + while (soap_blank(c)); + tp->visible = 2; /* seen this attribute w/ value */ + } + else + tp->visible = 1; /* seen this attribute w/o value */ + if (t && tp->value) + { if (soap_push_namespace(soap, t, tp->value)) + return soap->error; + tp->visible = 0; + } + } + if ((int)c == EOF) + return soap->error = SOAP_EOF; + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible && tp->value) + { if (!strcmp(tp->name, "id")) + { if (soap->part != SOAP_IN_HEADER || !soap->dot_net_bug) + { *soap->id = '#'; + strncpy(soap->id + 1, tp->value, sizeof(soap->id) - 2); + } + } + else if (soap->version == 1 && !strcmp(tp->name, "href")) + strncpy(soap->href, tp->value, sizeof(soap->href) - 1); + else if (soap->version == 2 && !strcmp(tp->name, "ref")) + { *soap->href = '#'; + strncpy(soap->href + 1, tp->value, sizeof(soap->href) - 2); + } + else if (!soap_match_tag(soap, tp->name, "xsi:type")) + strncpy(soap->type, tp->value, sizeof(soap->type) - 1); + else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:arrayType")) + { s = soap_strrchr(tp->value, '['); + if (s && (size_t)(s - tp->value) < sizeof(soap->arrayType)) + { strncpy(soap->arrayType, tp->value, s - tp->value); + soap->arrayType[s - tp->value] = '\0'; + strncpy(soap->arraySize, s, sizeof(soap->arraySize) - 1); + } + else + strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1); + } + else if (soap->version == 2 && !soap_match_tag(soap, tp->name, "SOAP-ENC:itemType")) + strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1); + else if (soap->version == 2 && !soap_match_tag(soap, tp->name, "SOAP-ENC:arraySize")) + strncpy(soap->arraySize, tp->value, sizeof(soap->arraySize) - 1); + else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:offset")) + strncpy(soap->arrayOffset, tp->value, sizeof(soap->arrayOffset)); + else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:position")) + soap->position = soap_getposition(tp->value, soap->positions); + else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:root")) + soap->root = ((!strcmp(tp->value, "1") || !strcmp(tp->value, "true"))); + else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:actor") + || !soap_match_tag(soap, tp->name, "SOAP-ENV:role")) + { if ((!soap->actor || strcmp(soap->actor, tp->value)) + && strcmp(tp->value, "http://schemas.xmlsoap.org/soap/actor/next") + && strcmp(tp->value, "http://www.w3.org/2003/05/soap-envelope/role/next")) + soap->other = 1; + } + else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand") + && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true"))) + soap->mustUnderstand = 1; + else if ((!soap_match_tag(soap, tp->name, "xsi:null") + || !soap_match_tag(soap, tp->name, "xsi:nil")) + && (!strcmp(tp->value, "1") + || !strcmp(tp->value, "true"))) + soap->null = 1; + } + } + if (!(soap->body = (c != '/'))) + do c = soap_get(soap); + while (soap_blank(c)); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_retry(struct soap *soap) +{ soap->peeked = 1; + soap->error = SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_revert(struct soap *soap) +{ soap->peeked = 1; + if (soap->body) + soap->level--; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reverting last element (level=%u)\n", soap->level)); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_string_out(struct soap *soap, const char *s, int flag) +{ register const char *t; + register wchar c; + register wchar mask = 0x80000000; +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { soap->dom->data = soap_strdup(soap, s); /* check EOM */ + return SOAP_OK; + } +#endif + if (soap->mode & SOAP_C_UTFSTRING) + mask = 0; + t = s; + while ((c = *t++)) + { switch (c) + { + case 9: + if (flag) + { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, " ", 5)) + return soap->error; + s = t; + } + break; + case 10: + if (flag || !(soap->mode & SOAP_XML_CANONICAL)) + { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, " ", 5)) + return soap->error; + s = t; + } + break; + case 13: + if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, " ", 5)) + return soap->error; + s = t; + break; + case '&': + if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&", 5)) + return soap->error; + s = t; + break; + case '<': + if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "<", 4)) + return soap->error; + s = t; + break; + case '>': + if (!flag) + { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, ">", 4)) + return soap->error; + s = t; + } + break; + case '"': + if (flag) + { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, """, 6)) + return soap->error; + s = t; + } + break; + default: +#ifdef HAVE_MBTOWC + if (soap->mode & SOAP_C_MBSTRING) + { wchar_t wc; + register int m = mbtowc(&wc, t - 1, MB_CUR_MAX); + if (m > 0 && wc != c) + { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, wc)) + return soap->error; + s = t + m - 1; + continue; + } + } +#endif + if (c & mask) + { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned char)c)) + return soap->error; + s = t; + } + } + } + return soap_send_raw(soap, s, t - s - 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_string_in(struct soap *soap, int flag) +{ register char *s; + char *t = NULL; + register size_t i; + register int n = 0; + register int m = 0; + register wchar c; +#ifdef HAVE_WCTOMB + char buf[MB_LEN_MAX > 8 ? MB_LEN_MAX : 8]; +#else + char buf[8]; +#endif +#ifdef WITH_CDATA + if (!flag) + { register int state = 0; +#ifdef WITH_FAST + soap->labidx = 0; /* use look-aside buffer */ +#else + if (soap_new_block(soap)) + return NULL; +#endif + for (;;) + { +#ifdef WITH_FAST + register size_t k; + if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */ + return NULL; + s = soap->labbuf + soap->labidx; /* space to populate */ + k = soap->lablen - soap->labidx; /* number of bytes available */ + soap->labidx = soap->lablen; /* claim this space */ +#else + register size_t k = SOAP_BLKLEN; + if (!(s = (char*)soap_push_block(soap, k))) + return NULL; +#endif + for (i = 0; i < k; i++) + { if (m > 0) + { *s++ = *t++; /* copy multibyte characters */ + m--; + continue; + } + c = soap_getchar(soap); + if ((int)c == EOF) + goto end; + if (c >= 0x80 && !(soap->mode & SOAP_C_LATIN)) + { soap_unget(soap, c); + c = soap_getutf8(soap); + if (soap->mode & SOAP_C_UTFSTRING) + { if ((c & 0x80000000) && c >= -0x7FFFFF80 && c < AP) + { c &= 0x7FFFFFFF; + t = buf; + if (c < 0x0800) + *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); + else + { if (c < 0x010000) + *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + else + { if (c < 0x200000) + *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + else + { if (c < 0x04000000) + *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + else + { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + } + *t++ = (char)(0x80 | (c & 0x3F)); + m = (int)(t - buf) - 1; + t = buf; + *s++ = *t++; + continue; + } + } + } + switch (state) + { case 1: + if (c == ']') + state = 4; + *s++ = c; + continue; + case 2: + if (c == '-') + state = 6; + *s++ = c; + continue; + case 3: + if (c == '?') + state = 8; + *s++ = c; + continue; + /* CDATA */ + case 4: + if (c == ']') + state = 5; + else + state = 1; + *s++ = c; + continue; + case 5: + if (c == '>') + state = 0; + else + state = 1; + *s++ = c; + continue; + /* comment */ + case 6: + if (c == '-') + state = 7; + else + state = 2; + *s++ = c; + continue; + case 7: + if (c == '>') + state = 0; + else + state = 2; + *s++ = c; + continue; + /* PI */ + case 8: + if (c == '>') + state = 0; + else + state = 3; + *s++ = c; + continue; + } + switch (c) + { + case '/': + if (n > 0) + { c = soap_get1(soap); + if (c == '>') + n--; + soap_unget(soap, c); + } + *s++ = '/'; + break; + case '<': + c = soap_get1(soap); + if (c == '/') + { if (n == 0) + { c = TT; + goto end; + } + n--; + } + else if (c == '!') + { c = soap_get1(soap); + if (c == '[') + { do c = soap_get1(soap); + while ((int)c != EOF && c != '['); + if ((int)c == EOF) + goto end; + t = (char*)"![CDATA["; + state = 1; + } + else if (c == '-') + { if ((c = soap_get1(soap)) == '-') + state = 2; + t = (char*)"!-"; + soap_unget(soap, c); + } + else + { t = (char*)"!"; + soap_unget(soap, c); + } + *s++ = '<'; + break; + } + else if (c == '?') + state = 3; + else + n++; + soap_unget(soap, c); + *s++ = '<'; + break; + case '>': + *s++ = '>'; + break; + case '"': + *s++ = '"'; + break; + default: +#ifdef HAVE_WCTOMB + if (soap->mode & SOAP_C_MBSTRING) + { m = wctomb(buf, c & 0x7FFFFFFF); + if (m >= 1) + { t = buf; + *s++ = *t++; + m--; + } + else + *s++ = SOAP_UNKNOWN_CHAR; + } + else +#endif + *s++ = (char)(c & 0xFF); + } + } + } + } +#endif +#ifdef WITH_FAST + soap->labidx = 0; /* use look-aside buffer */ +#else + if (soap_new_block(soap)) + return NULL; +#endif + for (;;) + { +#ifdef WITH_FAST + register size_t k; + if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */ + return NULL; + s = soap->labbuf + soap->labidx; /* space to populate */ + k = soap->lablen - soap->labidx; /* number of bytes available */ + soap->labidx = soap->lablen; /* claim this space */ +#else + register size_t k = SOAP_BLKLEN; + if (!(s = (char*)soap_push_block(soap, k))) + return NULL; +#endif + for (i = 0; i < k; i++) + { if (m > 0) + { *s++ = *t++; /* copy multibyte characters */ + m--; + continue; + } + if (soap->mode & SOAP_C_UTFSTRING) + { if (((c = soap_get(soap)) & 0x80000000) && c >= -0x7FFFFF80 && c < AP) + { c &= 0x7FFFFFFF; + t = buf; + if (c < 0x0800) + *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); + else + { if (c < 0x010000) + *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + else + { if (c < 0x200000) + *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + else + { if (c < 0x04000000) + *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + else + { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + } + *t++ = (char)(0x80 | (c & 0x3F)); + m = (int)(t - buf) - 1; + t = buf; + *s++ = *t++; + continue; + } + } + else if (soap->mode & SOAP_C_LATIN) + c = soap_get(soap); + else + c = soap_getutf8(soap); + switch (c) + { + case TT: + if (n == 0) + goto end; + n--; + *s++ = '<'; + soap_unget(soap, '/'); + break; + case LT: + n++; + *s++ = '<'; + break; + case GT: + *s++ = '>'; + break; + case QT: + *s++ = '"'; + break; + case AP: + *s++ = '\''; + break; + case '/': + if (n > 0) + { c = soap_get(soap); + if (c == GT) + n--; + soap_unget(soap, c); + } + *s++ = '/'; + break; + case '<': + if (flag) + *s++ = '<'; + else + { *s++ = '&'; + t = (char*)"lt;"; + } + break; + case '>': + if (flag) + *s++ = '>'; + else + { *s++ = '&'; + t = (char*)"gt;"; + } + break; + case '"': + if (flag) + *s++ = '"'; + else + { *s++ = '&'; + t = (char*)"quot;"; + } + break; + default: + if ((int)c == EOF) + goto end; +#ifdef HAVE_WCTOMB + if (soap->mode & SOAP_C_MBSTRING) + { m = wctomb(buf, c & 0x7FFFFFFF); + if (m >= 1) + { t = buf; + *s++ = *t++; + m--; + } + else + *s++ = SOAP_UNKNOWN_CHAR; + } + else +#endif + *s++ = (char)(c & 0xFF); + } + } + } +end: + soap_unget(soap, c); + *s = '\0'; +#ifdef WITH_FAST + t = soap_strdup(soap, soap->labbuf); +#else + soap_size_block(soap, i+1); + t = soap_save_block(soap, NULL); +#endif + if (flag == 2) + if (soap_s2QName(soap, t, &t)) + return NULL; + return t; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_wstring_out(struct soap *soap, const wchar_t *s, int flag) +{ const char *t; + char tmp; + register wchar c; +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { soap->dom->wide = NULL; /* soap_malloc() ??? */ + return SOAP_OK; + } +#endif + while ((c = *s++)) + { switch (c) + { + case 9: + if (flag) + t = " "; + else + t = "\t"; + break; + case 10: + if (flag || !(soap->mode & SOAP_XML_CANONICAL)) + t = " "; + else + t = "\n"; + break; + case 13: + t = " "; + break; + case '&': + t = "&"; + break; + case '<': + t = "<"; + break; + case '>': + if (flag) + t = ">"; + else + t = ">"; + break; + case '"': + if (flag) + t = """; + else + t = "\""; + break; + default: + if (c > 0 && c < 0x80) + { tmp = (char)c; + if (soap_send_raw(soap, &tmp, 1)) + return soap->error; + } + else if (soap_pututf8(soap, (unsigned long)c)) + return soap->error; + continue; + } + if (soap_send(soap, t)) + return soap->error; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +wchar_t * +SOAP_FMAC2 +soap_wstring_in(struct soap *soap, int flag) +{ wchar_t *s; + register int i, n = 0; + register wchar c; + const char *t = NULL; + if (soap_new_block(soap)) + return NULL; + for (;;) + { if (!(s = (wchar_t*)soap_push_block(soap, sizeof(wchar_t)*SOAP_BLKLEN))) + return NULL; + for (i = 0; i < SOAP_BLKLEN; i++) + { if (t) + { *s++ = (wchar_t)*t++; + if (!*t) + t = NULL; + continue; + } + if (soap->mode & SOAP_C_LATIN) + c = soap_get(soap); + else + c = soap_getutf8(soap); + switch (c) + { + case TT: + if (n == 0) + goto end; + n--; + *s++ = '<'; + soap_unget(soap, '/'); + break; + case LT: + n++; + *s++ = '<'; + break; + case GT: + *s++ = '>'; + break; + case QT: + *s++ = '"'; + break; + case AP: + *s++ = '\''; + break; + case '/': + if (n > 0) + { c = soap_getutf8(soap); + if (c == GT) + n--; + soap_unget(soap, c); + } + *s++ = '/'; + break; + case '<': + if (flag) + *s++ = (wchar)'<'; + else + { *s++ = (wchar)'&'; + t = "lt;"; + } + break; + case '>': + if (flag) + *s++ = (wchar)'>'; + else + { *s++ = (wchar)'&'; + t = "gt;"; + } + break; + case '"': + if (flag) + *s++ = (wchar)'"'; + else + { *s++ = (wchar)'&'; + t = "quot;"; + } + break; + default: + if ((int)c == EOF) + goto end; + *s++ = (wchar_t)c & 0x7FFFFFFF; + } + } + } +end: + soap_unget(soap, c); + *s = '\0'; + soap_size_block(soap, sizeof(wchar_t) * (i + 1)); + return (wchar_t*)soap_save_block(soap, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_int2s(struct soap *soap, int n) +{ return soap_long2s(soap, (long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outint(struct soap *soap, const char *tag, int id, const int *p, const char *type, int n) +{ long m = (long)*p; + return soap_outlong(soap, tag, id, &m, type, n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2int(struct soap *soap, const char *s, int *p) +{ if (s) + { char *r; + *p = (int)soap_strtol(s, &r, 10); + if (*r) + return soap->error = SOAP_TYPE; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int * +SOAP_FMAC2 +soap_inint(struct soap *soap, const char *tag, int *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag)) + return NULL; + if (soap->null) + { if (soap->mode & SOAP_XML_NIL) + { soap->error = SOAP_NULL; + return NULL; + } + return p; + } + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":int") + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } + p = (int*)soap_id_enter(soap, soap->id, p, t, sizeof(int), 0); + if (p && soap->body && !*soap->href) + soap_s2int(soap, soap_value(soap), p); + else + p = (int*)soap_id_forward(soap, soap->href, p, t, sizeof(int)); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_long2s(struct soap *soap, long n) +{ sprintf(soap->tmpbuf, "%ld", n); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outlong(struct soap *soap, const char *tag, int id, const long *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_long2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2long(struct soap *soap, const char *s, long *p) +{ if (s) + { char *r; + *p = soap_strtol(s, &r, 10); + if (*r) + return soap->error = SOAP_TYPE; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +long * +SOAP_FMAC2 +soap_inlong(struct soap *soap, const char *tag, long *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag)) + return NULL; + if (soap->null) + { if (soap->mode & SOAP_XML_NIL) + { soap->error = SOAP_NULL; + return NULL; + } + return p; + } + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":int") + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } + p = (long*)soap_id_enter(soap, soap->id, p, t, sizeof(long), 0); + if (p && soap->body && !*soap->href) + soap_s2long(soap, soap_value(soap), p); + else + p = (long*)soap_id_forward(soap, soap->href, p, t, sizeof(long)); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_LONG642s(struct soap *soap, LONG64 n) +{ sprintf(soap->tmpbuf, SOAP_LONG_FORMAT, n); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outLONG64(struct soap *soap, const char *tag, int id, const LONG64 *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_LONG642s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2LONG64(struct soap *soap, const char *s, LONG64 *p) +{ if (s && sscanf(s, SOAP_LONG_FORMAT, p) != 1) + return soap->error = SOAP_TYPE; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +LONG64 * +SOAP_FMAC2 +soap_inLONG64(struct soap *soap, const char *tag, LONG64 *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag)) + return NULL; + if (soap->null) + { if (soap->mode & SOAP_XML_NIL) + { soap->error = SOAP_NULL; + return NULL; + } + return p; + } + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":integer") + && soap_match_tag(soap, soap->type, ":positiveInteger") + && soap_match_tag(soap, soap->type, ":negativeInteger") + && soap_match_tag(soap, soap->type, ":nonPositiveInteger") + && soap_match_tag(soap, soap->type, ":nonNegativeInteger") + && soap_match_tag(soap, soap->type, ":long") + && soap_match_tag(soap, soap->type, ":int") + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } + p = (LONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(LONG64), 0); + if (soap->body && !*soap->href) + soap_s2LONG64(soap, soap_value(soap), p); + else + p = (LONG64*)soap_id_forward(soap, soap->href, p, t, sizeof(LONG64)); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_byte2s(struct soap *soap, char n) +{ return soap_long2s(soap, (long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outbyte(struct soap *soap, const char *tag, int id, const char *p, const char *type, int n) +{ long m = (long)*p; + return soap_outlong(soap, tag, id, &m, type, n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2byte(struct soap *soap, const char *s, char *p) +{ if (s) + { long n; + char *r; + n = soap_strtol(s, &r, 10); + if (*r || n < -128 || n > 127) + return soap->error = SOAP_TYPE; + *p = (char)n; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_inbyte(struct soap *soap, const char *tag, char *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag)) + return NULL; + if (soap->null) + { if (soap->mode & SOAP_XML_NIL) + { soap->error = SOAP_NULL; + return NULL; + } + return p; + } + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } + p = (char*)soap_id_enter(soap, soap->id, p, t, sizeof(char), 0); + if (soap->body && !*soap->href) + soap_s2byte(soap, soap_value(soap), p); + else + p = (char*)soap_id_forward(soap, soap->href, p, t, sizeof(char)); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_short2s(struct soap *soap, short n) +{ return soap_long2s(soap, (long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outshort(struct soap *soap, const char *tag, int id, const short *p, const char *type, int n) +{ long m = (long)*p; + return soap_outlong(soap, tag, id, &m, type, n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2short(struct soap *soap, const char *s, short *p) +{ if (s) + { long n; + char *r; + n = soap_strtol(s, &r, 10); + if (*r || n < -32768 || n > 32767) + return soap->error = SOAP_TYPE; + *p = (char)n; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +short * +SOAP_FMAC2 +soap_inshort(struct soap *soap, const char *tag, short *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag)) + return NULL; + if (soap->null) + { if (soap->mode & SOAP_XML_NIL) + { soap->error = SOAP_NULL; + return NULL; + } + return p; + } + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } + p = (short*)soap_id_enter(soap, soap->id, p, t, sizeof(short), 0); + if (soap->body && !*soap->href) + soap_s2short(soap, soap_value(soap), p); + else + p = (short*)soap_id_forward(soap, soap->href, p, t, sizeof(short)); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_float2s(struct soap *soap, float n) +{ const char *s; + if (isnan(n)) + s = "NaN"; + else if (n >= FLT_PINFTY) + s = "INF"; + else if (n <= FLT_NINFTY) + s = "-INF"; + else + { sprintf(soap->tmpbuf, soap->float_format, n); + s = soap->tmpbuf; + } + return s; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outfloat(struct soap *soap, const char *tag, int id, const float *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_float2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2float(struct soap *soap, const char *s, float *p) +{ if (s) + { if (!soap_tag_cmp(s, "INF")) + *p = FLT_PINFTY; + else if (!soap_tag_cmp(s, "+INF")) + *p = FLT_PINFTY; + else if (!soap_tag_cmp(s, "-INF")) + *p = FLT_NINFTY; + else if (!soap_tag_cmp(s, "NaN")) + *p = FLT_NAN; + else + { +#ifdef HAVE_STRTOD + char *r; + *p = (float)strtod(s, &r); + if (*r) +#endif + if (sscanf(s, soap->float_format, p) != 1) + return soap->error = SOAP_TYPE; + } + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +static int soap_isnumeric(struct soap *soap, const char *type) +{ if (soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":float") + && soap_match_tag(soap, soap->type, ":double") + && soap_match_tag(soap, soap->type, ":decimal") + && soap_match_tag(soap, soap->type, ":integer") + && soap_match_tag(soap, soap->type, ":positiveInteger") + && soap_match_tag(soap, soap->type, ":negativeInteger") + && soap_match_tag(soap, soap->type, ":nonPositiveInteger") + && soap_match_tag(soap, soap->type, ":nonNegativeInteger") + && soap_match_tag(soap, soap->type, ":long") + && soap_match_tag(soap, soap->type, ":int") + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte") + && soap_match_tag(soap, soap->type, ":unsignedLong") + && soap_match_tag(soap, soap->type, ":unsignedInt") + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return SOAP_ERR; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +float * +SOAP_FMAC2 +soap_infloat(struct soap *soap, const char *tag, float *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag)) + return NULL; + if (soap->null) + { if (soap->mode & SOAP_XML_NIL) + { soap->error = SOAP_NULL; + return NULL; + } + return p; + } + if (*soap->type != '\0' && soap_isnumeric(soap, type)) + return NULL; + p = (float*)soap_id_enter(soap, soap->id, p, t, sizeof(float), 0); + if (soap->body && !*soap->href) + soap_s2float(soap, soap_value(soap), p); + else + p = (float*)soap_id_forward(soap, soap->href, p, t, sizeof(float)); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_double2s(struct soap *soap, double n) +{ const char *s; + if (isnan(n)) + s = "NaN"; + else if (n >= DBL_PINFTY) + s = "INF"; + else if (n <= DBL_NINFTY) + s = "-INF"; + else + { sprintf(soap->tmpbuf, soap->double_format, n); + s = soap->tmpbuf; + } + return s; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outdouble(struct soap *soap, const char *tag, int id, const double *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_double2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2double(struct soap *soap, const char *s, double *p) +{ if (s) + { if (!soap_tag_cmp(s, "INF")) + *p = DBL_PINFTY; + else if (!soap_tag_cmp(s, "+INF")) + *p = DBL_PINFTY; + else if (!soap_tag_cmp(s, "-INF")) + *p = DBL_NINFTY; + else if (!soap_tag_cmp(s, "NaN")) + *p = DBL_NAN; + else + { +#ifdef HAVE_STRTOD + char *r; + *p = strtod(s, &r); + if (*r) +#endif + if (sscanf(s, soap->double_format, p) != 1) + return soap->error = SOAP_TYPE; + } + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +double * +SOAP_FMAC2 +soap_indouble(struct soap *soap, const char *tag, double *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag)) + return NULL; + if (soap->null) + { if (soap->mode & SOAP_XML_NIL) + { soap->error = SOAP_NULL; + return NULL; + } + return p; + } + if (*soap->type != '\0' && soap_isnumeric(soap, type)) + return NULL; + p = (double*)soap_id_enter(soap, soap->id, p, t, sizeof(double), 0); + if (soap->body && !*soap->href) + soap_s2double(soap, soap_value(soap), p); + else + p = (double*)soap_id_forward(soap, soap->href, p, t, sizeof(double)); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_unsignedByte2s(struct soap *soap, unsigned char n) +{ return soap_unsignedLong2s(soap, (unsigned long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outunsignedByte(struct soap *soap, const char *tag, int id, const unsigned char *p, const char *type, int n) +{ unsigned long m = (unsigned long)*p; + return soap_outunsignedLong(soap, tag, id, &m, type, n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2unsignedByte(struct soap *soap, const char *s, unsigned char *p) +{ if (s) + { unsigned long n; + char *r; + n = soap_strtoul(s, &r, 10); + if (*r || n > 255) + return soap->error = SOAP_TYPE; + *p = (unsigned char)n; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +unsigned char * +SOAP_FMAC2 +soap_inunsignedByte(struct soap *soap, const char *tag, unsigned char *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag)) + return NULL; + if (soap->null) + { if (soap->mode & SOAP_XML_NIL) + { soap->error = SOAP_NULL; + return NULL; + } + return p; + } + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } + p = (unsigned char*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned char), 0); + if (soap->body && !*soap->href) + soap_s2unsignedByte(soap, soap_value(soap), p); + else + p = (unsigned char*)soap_id_forward(soap, soap->href, p, t, sizeof(unsigned char)); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_unsignedShort2s(struct soap *soap, unsigned short n) +{ return soap_unsignedLong2s(soap, (unsigned long)n); +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outunsignedShort(struct soap *soap, const char *tag, int id, const unsigned short *p, const char *type, int n) +{ unsigned long m = (unsigned long)*p; + return soap_outunsignedLong(soap, tag, id, &m, type, n); +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2unsignedShort(struct soap *soap, const char *s, unsigned short *p) +{ if (s) + { unsigned long n; + char *r; + n = soap_strtoul(s, &r, 10); + if (*r || n > 65535) + return soap->error = SOAP_TYPE; + *p = (unsigned short)n; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +unsigned short * +SOAP_FMAC2 +soap_inunsignedShort(struct soap *soap, const char *tag, unsigned short *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag)) + return NULL; + if (soap->null) + { if (soap->mode & SOAP_XML_NIL) + { soap->error = SOAP_NULL; + return NULL; + } + return p; + } + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } + p = (unsigned short*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned short), 0); + if (soap->body && !*soap->href) + soap_s2unsignedShort(soap, soap_value(soap), p); + else + p = (unsigned short*)soap_id_forward(soap, soap->href, p, t, sizeof(unsigned short)); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_unsignedInt2s(struct soap *soap, unsigned int n) +{ return soap_unsignedLong2s(soap, (unsigned long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outunsignedInt(struct soap *soap, const char *tag, int id, const unsigned int *p, const char *type, int n) +{ unsigned long m = (unsigned long)*p; + return soap_outunsignedLong(soap, tag, id, &m, type, n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2unsignedInt(struct soap *soap, const char *s, unsigned int *p) +{ if (s) + { char *r; + *p = (unsigned int)soap_strtoul(s, &r, 10); + if (*r) + return soap->error = SOAP_TYPE; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +unsigned int * +SOAP_FMAC2 +soap_inunsignedInt(struct soap *soap, const char *tag, unsigned int *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag)) + return NULL; + if (soap->null) + { if (soap->mode & SOAP_XML_NIL) + { soap->error = SOAP_NULL; + return NULL; + } + return p; + } + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":unsignedInt") + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } + p = (unsigned int*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned int), 0); + if (soap->body && !*soap->href) + soap_s2unsignedInt(soap, soap_value(soap), p); + else + p = (unsigned int*)soap_id_forward(soap, soap->href, p, t, sizeof(unsigned int)); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_unsignedLong2s(struct soap *soap, unsigned long n) +{ sprintf(soap->tmpbuf, "%lu", n); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outunsignedLong(struct soap *soap, const char *tag, int id, const unsigned long *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_unsignedLong2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2unsignedLong(struct soap *soap, const char *s, unsigned long *p) +{ if (s) + { char *r; + *p = soap_strtoul(s, &r, 10); + if (*r) + return soap->error = SOAP_TYPE; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +unsigned long * +SOAP_FMAC2 +soap_inunsignedLong(struct soap *soap, const char *tag, unsigned long *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag)) + return NULL; + if (soap->null) + { if (soap->mode & SOAP_XML_NIL) + { soap->error = SOAP_NULL; + return NULL; + } + return p; + } + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":unsignedInt") + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } + p = (unsigned long*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned long), 0); + if (soap->body && !*soap->href) + soap_s2unsignedLong(soap, soap_value(soap), p); + else + p = (unsigned long*)soap_id_forward(soap, soap->href, p, t, sizeof(unsigned long)); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_ULONG642s(struct soap *soap, ULONG64 n) +{ sprintf(soap->tmpbuf, SOAP_ULONG_FORMAT, n); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outULONG64(struct soap *soap, const char *tag, int id, const ULONG64 *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_ULONG642s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2ULONG64(struct soap *soap, const char *s, ULONG64 *p) +{ if (s && sscanf(s, SOAP_ULONG_FORMAT, p) != 1) + return soap->error = SOAP_TYPE; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +ULONG64 * +SOAP_FMAC2 +soap_inULONG64(struct soap *soap, const char *tag, ULONG64 *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag)) + return NULL; + if (soap->null) + { if (soap->mode & SOAP_XML_NIL) + { soap->error = SOAP_NULL; + return NULL; + } + return p; + } + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":positiveInteger") + && soap_match_tag(soap, soap->type, ":nonNegativeInteger") + && soap_match_tag(soap, soap->type, ":unsignedLong") + && soap_match_tag(soap, soap->type, ":unsignedInt") + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } + p = (ULONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(ULONG64), 0); + if (soap->body && !*soap->href) + soap_s2ULONG64(soap, soap_value(soap), p); + else + p = (ULONG64*)soap_id_forward(soap, soap->href, p, t, sizeof(ULONG64)); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2string(struct soap *soap, const char *s, char **t) +{ *t = NULL; + if (s && !(*t = soap_strdup(soap, s))) + return soap->error = SOAP_EOM; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2QName(struct soap *soap, const char *s, char **t) +{ if (s) + { struct soap_nlist *np = soap->nlist; + const char *p = strchr(s, ':'); + if (p) + { int n = p - s; + while (np && (np->index == -2 || strncmp(np->id, s, n) || np->id[n])) + np = np->next; + p++; + } + else + { while (np && *np->id) + np = np->next; + p = s; + } + if (np) + { if (np->index >= 0 && soap->local_namespaces) + { const char *q = soap->local_namespaces[np->index].id; + if (q) + { if ((*t = (char*)soap_malloc(soap, strlen(p) + strlen(q) + 2))) + sprintf(*t, "%s:%s", q, p); + return SOAP_OK; + } + } + if (np->ns) + { if ((*t = (char*)soap_malloc(soap, strlen(p) + strlen(np->ns) + 4))) + sprintf(*t, "\"%s\":%s", np->ns, p); + return SOAP_OK; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Namespace prefix of '%s' not defined (index=%d, URI=%s)\n", s, np->index, np->ns?np->ns:"")); + return soap->error = SOAP_NAMESPACE; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Namespace prefix of '%s' not defined, assuming empty namespace\n", s)); + if ((*t = (char*)soap_malloc(soap, strlen(p) + 4))) + sprintf(*t, "\"\":%s", p); + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_QName2s(struct soap *soap, const char *s) +{ struct Namespace *p; + char *t; + int n; + if (!s || *s != '"') + return s; + s++; + if ((p = soap->local_namespaces)) + { for (; p->id; p++) + { if (p->ns) + if (!soap_tag_cmp(s, p->ns)) + break; + if (p->in) + if (!soap_tag_cmp(s, p->in)) + break; + } + if (p && p->id) + { s = strchr(s, '"'); + if (s) + { t = (char*)soap_malloc(soap, strlen(p->id) + strlen(s)); + strcpy(t, p->id); + strcat(t, s + 1); + return t; + } + } + } + t = (char*)strchr(s, '"'); + if (t) + n = t - s; + else + n = 0; + t = soap_strdup(soap, s); + t[n] = '\0'; + sprintf(soap->tmpbuf, "xmlns:_%lu", soap->idnum++); + soap_set_attr(soap, soap->tmpbuf, t); + s = strchr(s, '"'); + if (s) + { t = (char*)soap_malloc(soap, strlen(soap->tmpbuf) + strlen(s) - 6); + strcpy(t, soap->tmpbuf + 6); + strcat(t, s + 1); + } + return t; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outstring(struct soap *soap, const char *tag, int id, char *const*p, const char *type, int n) +{ if (!*p) + { if (soap_element_null(soap, tag, id, type)) + return soap->error; + } + else + { struct soap_plist *pp; + int i = soap_pointer_lookup(soap, *p, n, &pp); + if (id > 0) + { if (i) + { if (soap_element_begin_out(soap, tag, id, type) || soap_string_out(soap, *p, 0) || soap_element_end_out(soap, tag)) + return soap->error; + soap_set_embedded(soap, pp); + } + else + { i = soap_pointer_enter(soap, *p, n, &pp); + if (soap_element_begin_out(soap, tag, id, type) || soap_string_out(soap, *p, 0) || soap_element_end_out(soap, tag)) + return soap->error; + if (soap->mode & SOAP_IO_LENGTH) + pp->mark1 = 0; + else + pp->mark2 = 0; + } + } + else if (i) + { if (soap_is_embedded(soap, pp)) + { if (soap_element_ref(soap, tag, 0, i)) + return soap->error; + } + else if (soap_is_single(soap, pp)) + { if (soap_element_begin_out(soap, tag, 0, type) || soap_string_out(soap, *p, 0) || soap_element_end_out(soap, tag)) + return soap->error; + } + else + { if (soap_element_begin_out(soap, tag, i, type) || soap_string_out(soap, *p, 0) || soap_element_end_out(soap, tag)) + return soap->error; + soap_set_embedded(soap, pp); + } + } + else + { soap_pointer_enter(soap, *p, n, &pp); + if (soap_element_begin_out(soap, tag, id, type) || soap_string_out(soap, *p, 0) || soap_element_end_out(soap, tag)) + return soap->error; + if (soap->mode & SOAP_IO_LENGTH) + pp->mark1 = 0; + else + pp->mark2 = 0; + } + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char ** +SOAP_FMAC2 +soap_instring(struct soap *soap, const char *tag, char **p, const char *type, int t, int flag) +{ if (soap_element_begin_in(soap, tag)) + return NULL; + if (soap->null) + { p = (char**)soap_id_enter(soap, soap->id, p, t, sizeof(char**), 0); + if (p) + *p = NULL; + } + else if (soap->body && !*soap->href) + { if (soap_match_tag(soap, soap->type, "PointerTostring") == 0) + { p = (char**)soap_id_enter(soap, soap->id, p, t, sizeof(char**), 0); + p = (char**)soap_instring(soap, "string", p, type, t, flag); + } + else + { if (!p) + if ((p = (char**)soap_id_enter(soap, SOAP_STR_EOS, p, t, sizeof(char**), 0)) == NULL) + return NULL; + *p = (char*)soap_id_enter(soap, soap->id, soap_string_in(soap, flag), t, 0, 0); + } + } + else + p = (char**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(char*), 0); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outwstring(struct soap *soap, const char *tag, int id, wchar_t *const*p, const char *type, int n) +{ if (!*p) + { if (soap_element_null(soap, tag, id, type)) + return soap->error; + } + else + { struct soap_plist *pp; + int i = soap_pointer_lookup(soap, *p, n, &pp); + if (id > 0) + { if (i) + { if (soap_element_begin_out(soap, tag, id, type) || soap_wstring_out(soap, *p, 0) || soap_element_end_out(soap, tag)) + return soap->error; + soap_set_embedded(soap, pp); + } + else + { i = soap_pointer_enter(soap, *p, n, &pp); + if (soap_element_begin_out(soap, tag, id, type) || soap_wstring_out(soap, *p, 0) || soap_element_end_out(soap, tag)) + return soap->error; + if (soap->mode & SOAP_IO_LENGTH) + pp->mark1 = 0; + else + pp->mark2 = 0; + } + } + else if (i) + { if (soap_is_embedded(soap, pp)) + { if (soap_element_ref(soap, tag, 0, i)) + return soap->error; + } + else if (soap_is_single(soap, pp)) + { if (soap_element_begin_out(soap, tag, 0, type) || soap_wstring_out(soap, *p, 0) || soap_element_end_out(soap, tag)) + return soap->error; + } + else + { if (soap_element_begin_out(soap, tag, i, type) || soap_wstring_out(soap, *p, 0) || soap_element_end_out(soap, tag)) + return soap->error; + soap_set_embedded(soap, pp); + } + } + else + { if (soap_element_begin_out(soap, tag, id, type) || soap_wstring_out(soap, *p, 0) || soap_element_end_out(soap, tag)) + return soap->error; + if (soap->mode & SOAP_IO_LENGTH) + pp->mark1 = 0; + else + pp->mark2 = 0; + } + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +wchar_t ** +SOAP_FMAC2 +soap_inwstring(struct soap *soap, const char *tag, wchar_t **p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag)) + return NULL; + if (soap->null) + { p = (wchar_t**)soap_id_enter(soap, soap->id, p, t, sizeof(wchar_t**), 0); + if (p) + *p = NULL; + } + else if (soap->body && !*soap->href) + { if (soap_match_tag(soap, soap->type, "PointerTostring") == 0) + p = (wchar_t**)soap_inwstring(soap, "string", (wchar_t**)soap_id_enter(soap, soap->id, p, t, sizeof(wchar_t**), 0), type, t); + else + { if (!p) + if (!(p = (wchar_t**)soap_id_enter(soap, SOAP_STR_EOS, p, t, sizeof(wchar_t**), 0))) + return NULL; + *p = (wchar_t*)soap_id_enter(soap, soap->id, soap_wstring_in(soap, 1), t, 0, 0); + } + } + else + p = (wchar_t**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(wchar_t*), 0); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static time_t +soap_timegm(struct tm *T) +{ +#if defined(HAVE_TIMEGM) + return timegm(T); +#elif defined(HAVE_GETTIMEOFDAY) + struct timezone t; + struct timeval tv; + gettimeofday(&tv, &t); /* doesn't work properly on Solaris */ + T->tm_min -= t.tz_minuteswest; + T->tm_isdst = (t.tz_dsttime != 0); + return mktime(T); +/* WR[ */ + /* The following define was added for VxWorks*/ +#elif defined(HAVE_MKTIME) + /* FOR VXWORKS: + vxWorks does not seem to have any variable representation of time zones, but + timezone information can be set in INSTALL_DIR/target/h/private/timeP.h header + file, by setting the ZONEBUFFER define. The ZONEBUFFER define follows this + format: + + name_of_zone:<(unused)>:time_in_minutes_from_UTC:daylight_start:daylight_end + + To calculate local time, the value of time_in_minutes_from_UTC is subtracted + from UTC; time_in_minutes_from_UTC must be positive. Daylight information is + expressed as mmddhh (month-day-hour), for example: + + UTC::0:040102:100102 + + */ + return mktime(T); +/* ]WR */ +#elif defined(HAVE_FTIME) + struct timeb t; + t.timezone = 0; + t.dstflag = -1; + ftime(&t); + T->tm_min -= t.timezone; + T->tm_isdst = t.dstflag; /* doesn't work properly on Solaris */ + return mktime(T); +#else +#warning "time_t (de)serialization is not MT safe on this platform" + time_t t; + char *tz = getenv("TZ"); + putenv("TZ=UTC"); + tzset(); + t = mktime(T); + if (tz) + { char tmp[16]; + strcpy(tmp, "TZ="); + strncat(tmp, tz, 12); + tmp[15] = '\0'; + putenv(tmp); + } + else + putenv("TZ="); + tzset(); + return t; +#endif +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_dateTime2s(struct soap *soap, time_t n) +{ struct tm T; + struct tm *pT = &T; +#if defined(HAVE_GMTIME_R) + if (gmtime_r(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); +/* WR[ */ + /* The following defines were added for VxWorks*/ +#elif defined(HAVE_PGMTIME_R) + if (gmtime_r(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); +#elif defined(HAVE_PGMTIME) + if (gmtime(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); +/* ]WR */ +#elif defined(HAVE_GMTIME) + if ((pT = gmtime(&n))) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); +#elif defined(HAVE_GETTIMEOFDAY) + struct timezone t; +#if defined(HAVE_LOCALTIME_R) + if (localtime_r(&n, pT)) + { struct timeval tv; + gettimeofday(&tv, &t); + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.tz_minuteswest/60-(t.tz_dsttime!=0), abs(t.tz_minuteswest)%60); + } +#else + if ((pT = localtime(&n))) + { struct timeval tv; + gettimeofday(&tv, &t); + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.tz_minuteswest/60-(t.tz_dsttime!=0), abs(t.tz_minuteswest)%60); + } +#endif +#elif defined(HAVE_FTIME) + struct timeb t; +#if defined(HAVE_LOCALTIME_R) + if (localtime_r(&n, pT)) + { ftime(&t); + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60-(t.dstflag!=0), abs(t.timezone)%60); + } +/* WR[ */ + /* The following defines were added for VxWorks*/ +#elif defined(HAVE_PLOCALTIME_R) + if (localtime_r(&n, pT)) + { strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf+strlen(soap->tmpbuf), "%+03d:%02d", t.timezone/60, abs(t.timezone)%60); + } +/* ]WR */ +#else + if ((pT = localtime(&n))) + { ftime(&t); + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60-(t.dstflag!=0), abs(t.timezone)%60); + } +#endif +#elif defined(HAVE_LOCALTIME_R) + if (localtime_r(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); +/* WR[ */ + /* The following defines were added for VxWorks*/ +#elif defined(HAVE_PLOCALTIME_R) + if (localtime_r(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); +/* ]WR */ +#else + if ((pT = localtime(&n))) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); +#endif + else + strcpy(soap->tmpbuf, "1969-12-31T23:59:59Z"); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outdateTime(struct soap *soap, const char *tag, int id, const time_t *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_dateTime2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2dateTime(struct soap *soap, const char *s, time_t *p) +{ if (s) + { struct tm T; + char zone[16]; + memset(&T, 0, sizeof(struct tm)); + zone[sizeof(zone)-1] = '\0'; + sscanf(s, "%d-%d-%dT%d:%d:%d%15s", &T.tm_year, &T.tm_mon, &T.tm_mday, &T.tm_hour, &T.tm_min, &T.tm_sec, zone); + if (T.tm_year == 1) + T.tm_year = 70; + else + T.tm_year -= 1900; + T.tm_mon--; + if (*zone) + { if (*zone == '.') + { for (s = zone + 1; *s; s++) + if (*s < '0' || *s > '9') + break; + } + else + s = zone; + if (*s != 'Z') + { int h = 0, m = 0; + sscanf(s, "%d:%d", &h, &m); + T.tm_hour -= h; + if (h >= 0) + T.tm_min -= m; + else + T.tm_min += m; + } + *p = soap_timegm(&T); + } + else + *p = mktime(&T); /* no time zone: suppose it is localtime? */ + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +time_t * +SOAP_FMAC2 +soap_indateTime(struct soap *soap, const char *tag, time_t *p, const char * type, int t) +{ if (soap_element_begin_in(soap, tag)) + return NULL; + if (soap->null) + { if (soap->mode & SOAP_XML_NIL) + { soap->error = SOAP_NULL; + return NULL; + } + return p; + } + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":dateTime")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } + p = (time_t*)soap_id_enter(soap, soap->id, p, t, sizeof(time_t), 0); + if (soap->body && !*soap->href) + soap_s2dateTime(soap, soap_value(soap), p); + else + p = (time_t*)soap_id_forward(soap, soap->href, p, t, sizeof(time_t)); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outliteral(struct soap *soap, const char *tag, char *const*p) +{ int i; + const char *t = NULL; + if (tag && *tag != '-') + { if ((t = strchr(tag, ':'))) + { strncpy(soap->tmpbuf, tag, t-tag); + soap->tmpbuf[t-tag] = '\0'; + for (i = 0; soap->local_namespaces[i].id; i++) + if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id)) + break; + t++; + sprintf(soap->tmpbuf, "<%s xmlns=\"%s\">", t, soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS); + } + else + { t = tag; + sprintf(soap->tmpbuf, "<%s>", tag); + } + if (soap_send(soap, soap->tmpbuf)) + return soap->error; + } + if (p && *p) + { if (soap_send(soap, *p)) + return soap->error; + } + if (t) + { sprintf(soap->tmpbuf, "", t); + return soap_send(soap, soap->tmpbuf); + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char ** +SOAP_FMAC2 +soap_inliteral(struct soap *soap, const char *tag, char **p) +{ if (soap_element_begin_in(soap, tag)) + return NULL; + if (!p) + if (!(p = (char**)soap_malloc(soap, sizeof(char*)))) + return NULL; + if (soap->null) + *p = NULL; + else if (soap->body) + *p = soap_string_in(soap, 0); + else + *p = NULL; + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outwliteral(struct soap *soap, const char *tag, wchar_t *const*p) +{ int i; + const char *t = NULL; + wchar_t c; + const wchar_t *s; + if (tag && *tag != '-') + { if (tag && (t = strchr(tag, ':'))) + { strncpy(soap->tmpbuf, tag, t-tag); + soap->tmpbuf[t-tag] = '\0'; + for (i = 0; soap->local_namespaces[i].id; i++) + if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id)) + break; + t++; + sprintf(soap->tmpbuf, "<%s xmlns=\"%s\">", t, soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS); + } + else + { t = tag; + sprintf(soap->tmpbuf, "<%s>", tag); + } + if (soap_send(soap, soap->tmpbuf)) + return soap->error; + } + if (p) + { s = *p; + while ((c = *s++)) + if (soap_pututf8(soap, (unsigned char)c)) + return soap->error; + } + if (t) + { sprintf(soap->tmpbuf, "", t); + return soap_send(soap, soap->tmpbuf); + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +wchar_t ** +SOAP_FMAC2 +soap_inwliteral(struct soap *soap, const char *tag, wchar_t **p) +{ if (soap_element_begin_in(soap, tag)) + return NULL; + if (!p) + if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*)))) + return NULL; + if (soap->null) + *p = NULL; + else if (soap->body) + *p = soap_wstring_in(soap, 0); + else + *p = NULL; + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_value(struct soap *soap) +{ size_t i; + wchar c = 0; + char *s; + s = soap->tmpbuf; + for (i = 0; i < sizeof(soap->tmpbuf) - 1; i++) + { c = soap_get(soap); + if (c == TT || (int)c == EOF || soap_blank(c)) + break; + *s++ = (char)c; + } + if ((int)c == EOF || c == TT) + soap_unget(soap, c); + *s = '\0'; + return soap->tmpbuf; /* return non-null pointer */ +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getline(struct soap *soap, char *s, int len) +{ int i = len; + wchar c = 0; + for (;;) + { while (--i > 0) + { c = soap_getchar(soap); + if (c == '\r' || c == '\n' || (int)c == EOF) + break; + *s++ = (char)c; + } + *s = '\0'; + while (c != '\n' && (int)c != EOF) + c = soap_getchar(soap); + if ((int)c == EOF) + return SOAP_EOF; + if (i+1 == len) /* empty line: end of HTTP header */ + break; + c = soap_unget(soap, soap_getchar(soap)); + if (c != ' ' && c != '\t') /* HTTP line continuation? */ + break; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static size_t +soap_begin_dime(struct soap *soap) +{ +#ifndef WITH_LEANER + if (soap->mode & SOAP_ENC_DIME) + { size_t count; + sprintf(soap->id, soap->dime_id_format, 0); + soap->dime_id = soap->id; + if (soap->local_namespaces) + { if (soap->local_namespaces[0].out) + soap->dime_type = (char*)soap->local_namespaces[0].out; + else + soap->dime_type = (char*)soap->local_namespaces[0].ns; + } + soap->dime_options = NULL; + count = soap->dime_size + 12 + ((soap->count+3)&(~3)) + ((strlen(soap->dime_id)+3)&(~3)) + ((strlen(soap->dime_type)+3)&(~3)); + soap->dime_size = soap->count; + if (soap->dime_count) + soap->dime_flags = SOAP_DIME_MB | SOAP_DIME_ABSURI; + else + soap->dime_flags = SOAP_DIME_MB | SOAP_DIME_ME | SOAP_DIME_ABSURI; + return count; + } +#endif + return soap->count; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static int +soap_putdimefield(struct soap *soap, const char *s, size_t n) +{ if (soap_send_raw(soap, s, n)) + return soap->error; + return soap_send_raw(soap, SOAP_STR_PADDING, -(long)n&3); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_dime_option(struct soap *soap, unsigned short type, const char *option) +{ size_t n; + char *s = NULL; + if (option) + { n = strlen(option); + s = (char*)soap_malloc(soap, n + 5); + if (s) + { s[0] = type >> 8; + s[1] = type & 0xFF; + s[2] = n >> 8; + s[3] = n & 0xFF; + strcpy(s + 4, option); + } + } + return s; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putdimehdr(struct soap *soap) +{ unsigned char tmp[12]; + size_t optlen = 0, idlen = 0, typelen = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Put DIME header id='%s'\n", soap->dime_id?soap->dime_id:"")); + if (soap->dime_options) + optlen = (((unsigned char)soap->dime_options[2] << 8) | ((unsigned char)soap->dime_options[3])) + 4; + if (soap->dime_id) + idlen = strlen(soap->dime_id); + if (soap->dime_type) + typelen = strlen(soap->dime_type); + tmp[0] = SOAP_DIME_VERSION | (soap->dime_flags & 0x7); + tmp[1] = soap->dime_flags & 0xF0; + tmp[2] = optlen >> 8; + tmp[3] = optlen & 0xFF; + tmp[4] = idlen >> 8; + tmp[5] = idlen & 0xFF; + tmp[6] = typelen >> 8; + tmp[7] = typelen & 0xFF; + tmp[8] = soap->dime_size >> 24; + tmp[9] = (soap->dime_size >> 16) & 0xFF; + tmp[10] = (soap->dime_size >> 8) & 0xFF; + tmp[11] = soap->dime_size & 0xFF; + if (soap_send_raw(soap, (char*)tmp, 12) + || soap_putdimefield(soap, soap->dime_options, optlen) + || soap_putdimefield(soap, soap->dime_id, idlen) + || soap_putdimefield(soap, soap->dime_type, typelen)) + return soap->error; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putdime(struct soap *soap, int i, char *id, char *type, char *options, void *ptr, size_t size) +{ void *h; + if (id) + soap->dime_id = id; + else + { sprintf(soap->id, soap->dime_id_format, i); + soap->dime_id = soap->id; + } + soap->dime_type = type; + soap->dime_options = options; + soap->dime_size = size; + soap->dime_flags = SOAP_DIME_VERSION | SOAP_DIME_MEDIA; + if (soap->fdimereadopen && ((h = soap->fdimereadopen(soap, (void*)ptr, soap->dime_id, type, options)) || soap->error)) + { size_t n; + if (!h) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadopen failed\n")); + return soap->error; + } + if (!size && ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming DIME\n")); + n = sizeof(soap->tmpbuf); + do + { size = soap->fdimeread(soap, h, soap->tmpbuf, n); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread returned %lu bytes\n", (unsigned long)size)); + if (size == n) + soap->dime_flags |= SOAP_DIME_CF; + else + { soap->dime_flags &= ~SOAP_DIME_CF; + if (--soap->dime_count == 0) + soap->dime_flags |= SOAP_DIME_ME; + } + soap->dime_size = size; + if (soap_putdimehdr(soap) + || soap_send_raw(soap, soap->tmpbuf, size) + || soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime_size&3)) + break; + if (soap->dime_id) + { soap->dime_flags &= ~(SOAP_DIME_MB | SOAP_DIME_MEDIA); + soap->dime_id = NULL; + soap->dime_type = NULL; + soap->dime_options = NULL; + } + } while (size >= n); + } + else + { if (--soap->dime_count == 0) + soap->dime_flags |= SOAP_DIME_ME; + if (soap_putdimehdr(soap)) + return soap->error; + do + { if (size < sizeof(soap->tmpbuf)) + n = size; + else + n = sizeof(soap->tmpbuf); + if (!(n = soap->fdimeread(soap, h, soap->tmpbuf, n))) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)soap->dime_size)); + soap->error = SOAP_EOF; + break; + } + if (soap_send_raw(soap, soap->tmpbuf, n)) + break; + size -= n; + } while (size); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n")); + soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime_size&3); + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n")); + if (soap->fdimereadclose) + soap->fdimereadclose(soap, h); + return soap->error; + } + if (--soap->dime_count == 0) + soap->dime_flags |= SOAP_DIME_ME; + if (soap_putdimehdr(soap)) + return soap->error; + return soap_putdimefield(soap, (char*)ptr, size); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static char * +soap_getdimefield(struct soap *soap, size_t n) +{ register wchar c; + register int i; + register char *s; + char *p = NULL; + if (n) + { p = (char*)soap_malloc(soap, n + 1); + if (p) + { s = p; + for (i = n; i > 0; i--) + { if ((int)(c = soap_get1(soap)) == EOF) + { soap->error = SOAP_EOF; + return NULL; + } + *s++ = (char)c; + } + *s = '\0'; + if ((soap->error = soap_move(soap, -(long)n&3))) + return NULL; + } + else + soap->error = SOAP_EOM; + } + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getdimehdr(struct soap *soap) +{ register wchar c; + register char *s; + register int i; + unsigned char tmp[12]; + size_t optlen, idlen, typelen; + if (!(soap->mode & SOAP_ENC_DIME)) + return soap->error = SOAP_EOD; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME header\n")); + if (soap->dime_buflen || soap->dime_chunksize) + { if (soap_move(soap, (long)(soap->dime_size - soap_tell(soap)))) + return soap->error = SOAP_EOF; + soap_unget(soap, soap_getchar(soap)); /* skip padding and get hdr */ + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... From chunked\n")); + return SOAP_OK; + } + s = (char*)tmp; + for (i = 12; i > 0; i--) + { if ((int)(c = soap_getchar(soap)) == EOF) + return soap->error = SOAP_EOF; + *s++ = (char)c; + } + if ((tmp[0] & 0xF8) != SOAP_DIME_VERSION) + return soap->error = SOAP_DIME_MISMATCH; + soap->dime_flags = (tmp[0] & 0x7) | (tmp[1] & 0xF0); + optlen = (tmp[2] << 8) | tmp[3]; + idlen = (tmp[4] << 8) | tmp[5]; + typelen = (tmp[6] << 8) | tmp[7]; + soap->dime_size = (tmp[8] << 24) | (tmp[9] << 16) | (tmp[10] << 8) | tmp[11]; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME size=%u flags=0x%X\n", (unsigned int)soap->dime_size, soap->dime_flags)); + if (!(soap->dime_options = soap_getdimefield(soap, optlen)) && soap->error) + return soap->error; + if (!(soap->dime_id = soap_getdimefield(soap, idlen)) && soap->error) + return soap->error; + if (!(soap->dime_type = soap_getdimefield(soap, typelen)) && soap->error) + return soap->error; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME id=%s, type=%s, options=%s\n", soap->dime_id?soap->dime_id:"", soap->dime_type?soap->dime_type:"", soap->dime_options?soap->dime_options+4:"")); + if (soap->dime_flags & SOAP_DIME_ME) + soap->mode &= ~SOAP_ENC_DIME; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getdime(struct soap *soap) +{ if (soap_getdimehdr(soap)) + return soap->error; + if (soap->fdimewriteopen && ((soap->dime_ptr = (char*)soap->fdimewriteopen(soap, soap->dime_id, soap->dime_type, soap->dime_options)) || soap->error)) + { char *id, *type, *options; + size_t size, n; + if (!soap->dime_ptr) + return soap->error; + id = soap->dime_id; + type = soap->dime_type; + options = soap->dime_options; + for (;;) + { size = soap->dime_size; + for (;;) + { n = soap->buflen - soap->bufidx; + if (size < n) + n = size; + if ((soap->error = soap->fdimewrite(soap, (void*)soap->dime_ptr, soap->buf + soap->bufidx, n))) + break; + size -= n; + if (!size) + { soap->bufidx += n; + break; + } + if (soap_recv(soap)) + { soap->error = SOAP_EOF; + goto end; + } + } + if (soap_move(soap, -(long)soap->dime_size&3)) + { soap->error = SOAP_EOF; + break; + } + if (!(soap->dime_flags & SOAP_DIME_CF)) + break; + if (soap_getdimehdr(soap)) + break; + } +end: + if (soap->fdimewriteclose) + soap->fdimewriteclose(soap, (void*)soap->dime_ptr); + soap->dime_size = 0; + soap->dime_id = id; + soap->dime_type = type; + soap->dime_options = options; + } + else if (soap->dime_flags & SOAP_DIME_CF) + { char *id, *type, *options; + register wchar c; + register char *s; + register int i; + id = soap->dime_id; + type = soap->dime_type; + options = soap->dime_options; + if (soap_new_block(soap)) + return SOAP_EOM; + for (;;) + { s = (char*)soap_push_block(soap, soap->dime_size); + if (!s) + return soap->error = SOAP_EOM; + for (i = soap->dime_size; i > 0; i--) + { if ((int)(c = soap_get1(soap)) == EOF) + return soap->error = SOAP_EOF; + *s++ = (char)c; + } + if (soap_move(soap, -(long)soap->dime_size&3)) + return soap->error = SOAP_EOF; + if (!(soap->dime_flags & SOAP_DIME_CF)) + break; + if (soap_getdimehdr(soap)) + return soap->error; + } + soap->dime_size = soap->blist->size++; /* allocate one more for '\0' */ + if (!(soap->dime_ptr = soap_save_block(soap, NULL))) + return soap->error; + soap->dime_ptr[soap->dime_size] = '\0'; /* make 0-terminated to enable string-based attachments */ + soap->dime_id = id; + soap->dime_type = type; + soap->dime_options = options; + } + else + soap->dime_ptr = soap_getdimefield(soap, soap->dime_size); + return soap->error; +} +#endif +#endif + +/******************************************************************************/ + +#ifdef WITH_COOKIES +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_encode_cookie(const char *s, char *t, int len) +{ register int c; + register int n = len; + while ((c = *s++) && --n > 0) + { if (c > ' ' && c < 128 && c != ';' && c != ',') + *t++ = c; + else if (n > 2) + { *t++ = '%'; + *t++ = (c >> 4) + (c > 159 ? '7' : '0'); + c &= 0xF; + *t++ = c + (c > 9 ? '7' : '0'); + n -= 2; + } + else + break; + } + *t = '\0'; + return len - n; +} + +/******************************************************************************/ +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_decode_cookie(char *buf, int len, const char *val) +{ const char *s; + char *t; + for (s = val; *s; s++) + if (*s != ' ' && *s != '=') + break; + if (*s == '"') + { t = buf; + s++; + while (*s && *s != '"' && --len) + *t++ = *s++; + *t = '\0'; + do s++; + while (*s && *s != ';' && *s != '='); + } + else + { t = buf; + while (*s && *s != ';' && *s != '=' && --len) + switch (*s) + { case ' ': + s++; + break; + case '%': + *t++ = ((s[1] >= 'A' ? (s[1] & 0x7) + 9 : s[1] - '0') << 4) + + (s[2] >= 'A' ? (s[2] & 0x7) + 9 : s[2] - '0'); + s += 3; + break; + default: + *t++ = *s++; + } + *t = '\0'; + } + return s; +} + +/******************************************************************************/ +SOAP_FMAC1 +struct soap_cookie* +SOAP_FMAC2 +soap_cookie(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + size_t n; + if (!domain) + domain = soap->cookie_domain; + if (!path) + path = soap->cookie_path; + if (*path == '/') + path++; + n = strlen(path); + for (p = soap->cookies; p; p = p->next) + if (!strcmp(p->name, name) + && domain + && p->domain + && !strcmp(p->domain, domain) + && !strncmp(p->path, path, n)) + break; + return p; +} + +/******************************************************************************/ +SOAP_FMAC1 +struct soap_cookie* +SOAP_FMAC2 +soap_set_cookie(struct soap *soap, const char *name, const char *value, const char *domain, const char *path) +{ struct soap_cookie **p, *q; + int n; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set cookie: %s=%s domain=%s path=%s\n", name, value?value:"", domain?domain:"", path?path:"")); + if (!domain) + domain = soap->cookie_domain; + if (!path) + path = soap->cookie_path; + if (!path) + { soap_set_receiver_error(soap, "Cookie path not set", NULL, SOAP_HTTP_ERROR); + return NULL; + } + if (*path == '/') + path++; + q = soap_cookie(soap, name, domain, path); + if (!q) + { if ((q = (struct soap_cookie*)SOAP_MALLOC(sizeof(struct soap_cookie)))) + { if ((q->name = (char*)SOAP_MALLOC(strlen(name)+1))) + strcpy(q->name, name); + q->value = NULL; + q->domain = NULL; + q->path = NULL; + q->expire = -1; + q->version = 0; + q->secure = 0; + q->env = 0; + q->modified = 0; + for (p = &soap->cookies, n = soap->cookie_max; *p && n; p = &(*p)->next, n--) + if (!strcmp((*p)->name, name) && (*p)->path && strcmp((*p)->path, path) < 0) + break; + if (n) + { q->next = *p; + *p = q; + } + else + { SOAP_FREE(q->name); + SOAP_FREE(q); + q = NULL; + } + } + } + else + q->modified = 1; + if (q) + { if (q->value) + { SOAP_FREE(q->value); + q->value = NULL; + } + if (q->domain) + { SOAP_FREE(q->domain); + q->domain = NULL; + } + if (q->path) + { SOAP_FREE(q->path); + q->path = NULL; + } + if (value && *value && (q->value = (char*)SOAP_MALLOC(strlen(value)+1))) + strcpy(q->value, value); + if (domain && *domain && (q->domain = (char*)SOAP_MALLOC(strlen(domain)+1))) + strcpy(q->domain, domain); + if (path && *path && (q->path = (char*)SOAP_MALLOC(strlen(path)+1))) + strcpy(q->path, path); + q->session = 1; + } + return q; +} + +/******************************************************************************/ +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_clr_cookie(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie **p, *q; + if (!domain) + domain = soap->cookie_domain; + if (!domain) + { soap_set_receiver_error(soap, "Cookie domain not set", SOAP_STR_EOS, SOAP_HTTP_ERROR); + return; + } + if (!path) + path = soap->cookie_path; + if (!path) + { soap_set_receiver_error(soap, "Cookie path not set", SOAP_STR_EOS, SOAP_HTTP_ERROR); + return; + } + if (*path == '/') + path++; + for (p = &soap->cookies, q = *p; q; q = *p) + if (!strcmp(q->name, name) && !strcmp(q->domain, domain) && !strncmp(q->path, path, strlen(q->path))) + { if (q->value) + SOAP_FREE(q->value); + if (q->domain) + SOAP_FREE(q->domain); + if (q->path) + SOAP_FREE(q->path); + *p = q->next; + SOAP_FREE(q); + } + else + p = &q->next; +} + +/******************************************************************************/ +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + return p->value; + return NULL; +} + +/******************************************************************************/ +SOAP_FMAC1 +long +SOAP_FMAC2 +soap_cookie_expire(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + return p->expire; + return -1; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_cookie_expire(struct soap *soap, const char *name, long expire, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + { p->expire = expire; + p->modified = 1; + return SOAP_OK; + } + return SOAP_ERR; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + { p->session = 1; + p->modified = 1; + return SOAP_OK; + } + return SOAP_ERR; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_clr_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + { p->session = 0; + p->modified = 1; + return SOAP_OK; + } + return SOAP_ERR; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putsetcookies(struct soap *soap) +{ struct soap_cookie *p; + char *s, tmp[4096]; + const char *t; + for (p = soap->cookies; p; p = p->next) + if (p->modified || !p->env) + { s = tmp; + if (p->name) + s += soap_encode_cookie(p->name, s, tmp-s+4064); + if (p->value) + { *s++ = '='; + s += soap_encode_cookie(p->value, s, tmp-s+4064); + } + if (p->domain && (int)strlen(p->domain) < tmp-s+4064) + sprintf(s, ";Domain=%s", p->domain); + else if (soap->cookie_domain && (int)strlen(soap->cookie_domain) < tmp-s+4064) + sprintf(s, ";Domain=%s", soap->cookie_domain); + strcpy(s, ";Path=/"); + if (p->path) + t = p->path; + else + t = soap->cookie_path; + if (t) + { if (*t == '/') + t++; + if ((int)strlen(t) < tmp-s+4064) + strcat(s, t); + } + s += strlen(s); + if (p->version > 0) + { sprintf(s, ";Version=%u", p->version); + s += strlen(s); + } + if (p->expire >= 0) + { sprintf(s, ";Max-Age=%ld", p->expire); + s += strlen(s); + } + if (p->secure) + strcpy(s, ";Secure"); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set-Cookie: %s\n", tmp)); + if (soap->fposthdr(soap, "Set-Cookie", tmp)) + return soap->error; + } + return SOAP_OK; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putcookies(struct soap *soap, const char *domain, const char *path, int secure) +{ struct soap_cookie **p, *q; + unsigned int version = 0; + time_t now = time(NULL); + char *s, tmp[4096]; + p = &soap->cookies; + while ((q = *p)) + { if (q->expire && now > q->expire) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie %s expired\n", q->name)); + SOAP_FREE(q->name); + if (q->value) + SOAP_FREE(q->value); + if (q->domain) + SOAP_FREE(q->domain); + if (q->path) + SOAP_FREE(q->path); + *p = q->next; + SOAP_FREE(q); + } + else if ((!q->domain || !strcmp(q->domain, domain)) + && (!q->path || !strncmp(q->path, path, strlen(q->path))) + && (!q->secure || secure)) + { s = tmp; + if (q->version != version) + { sprintf(s, "$Version=%u;", q->version); + version = q->version; + } + if (q->name) + s += soap_encode_cookie(q->name, s, tmp-s+4080); + if (q->value) + { *s++ = '='; + s += soap_encode_cookie(q->value, s, tmp-s+4080); + } + if (q->path && (int)strlen(q->path) < tmp-s+4080) + { sprintf(s, ";$Path=/%s", q->path); + s += strlen(s); + } + if (q->domain && (int)strlen(q->domain) < tmp-s+4080) + sprintf(s, ";$Domain=%s", q->domain); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie: %s\n", tmp)); + if (soap->fposthdr(soap, "Cookie", tmp)) + return soap->error; + p = &q->next; + } + else + p = &q->next; + } + return SOAP_OK; +} + +/******************************************************************************/ +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_getcookies(struct soap *soap, const char *val) +{ struct soap_cookie *p = NULL, *q; + const char *s; + char *t, tmp[4096]; /* cookie size is up to 4096 bytes [RFC2109] */ + char *domain = NULL; + char *path = NULL; + unsigned int version = 0; + time_t now = time(NULL); + if (!val) + return; + s = val; + while (*s) + { s = soap_decode_cookie(tmp, sizeof(tmp), s); + if (!soap_tag_cmp(tmp, "$Version")) + { if ((s = soap_decode_cookie(tmp, sizeof(tmp), s))) + { if (p) + p->version = (int)atol(tmp); + else + version = (int)atol(tmp); + } + } + else if (!soap_tag_cmp(tmp, "$Path")) + { s = soap_decode_cookie(tmp, sizeof(tmp), s); + if (*tmp) + { if ((t = (char*)SOAP_MALLOC(strlen(tmp)+1))) + strcpy(t, tmp); + } + else + t = NULL; + if (p) + { if (p->path) + SOAP_FREE(p->path); + p->path = t; + } + else + { if (path) + SOAP_FREE(path); + path = t; + } + } + else if (!soap_tag_cmp(tmp, "$Domain")) + { s = soap_decode_cookie(tmp, sizeof(tmp), s); + if (*tmp) + { if ((t = (char*)SOAP_MALLOC(strlen(tmp)+1))) + strcpy(t, tmp); + } + else + t = NULL; + if (p) + { if (p->domain) + SOAP_FREE(p->domain); + p->domain = t; + } + else + { if (domain) + SOAP_FREE(domain); + domain = t; + } + } + else if (p && !soap_tag_cmp(tmp, "Path")) + { s = soap_decode_cookie(tmp, sizeof(tmp), s); + if (p->path) + SOAP_FREE(p->path); + if (*tmp) + { if ((p->path = (char*)SOAP_MALLOC(strlen(tmp)+1))) + strcpy(p->path, tmp); + } + else + p->path = NULL; + } + else if (p && !soap_tag_cmp(tmp, "Domain")) + { s = soap_decode_cookie(tmp, sizeof(tmp), s); + if (p->domain) + SOAP_FREE(p->domain); + if (*tmp) + { if ((p->domain = (char*)SOAP_MALLOC(strlen(tmp)+1))) + strcpy(p->domain, tmp); + } + else + p->domain = NULL; + } + else if (p && !soap_tag_cmp(tmp, "Version")) + { s = soap_decode_cookie(tmp, sizeof(tmp), s); + p->version = (unsigned int)atol(tmp); + } + else if (p && !soap_tag_cmp(tmp, "Max-Age")) + { s = soap_decode_cookie(tmp, sizeof(tmp), s); + p->expire = now + atol(tmp); + } + else if (p && !soap_tag_cmp(tmp, "Expires")) + { struct tm T; + char a[3]; + static const char mns[] = "anebarprayunulugepctovec"; + s = soap_decode_cookie(tmp, sizeof(tmp), s); + memset(&T, 0, sizeof(struct tm)); + a[0] = tmp[4]; + a[1] = tmp[5]; + a[2] = '\0'; + T.tm_mday = (int)atol(a); + a[0] = tmp[8]; + a[1] = tmp[9]; + T.tm_mon = (strstr(mns, a) - mns) / 2; + a[0] = tmp[11]; + a[1] = tmp[12]; + T.tm_year = 100 + (int)atol(a); + a[0] = tmp[13]; + a[1] = tmp[14]; + T.tm_hour = (int)atol(a); + a[0] = tmp[16]; + a[1] = tmp[17]; + T.tm_min = (int)atol(a); + a[0] = tmp[19]; + a[1] = tmp[20]; + T.tm_sec = (int)atol(a); + p->expire = soap_timegm(&T); + } + else if (p && !soap_tag_cmp(tmp, "Secure")) + p->secure = 1; + else + { if (p) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie %s=%s domain=%s path=%s expire=%ld secure=%d\n", p->name, p->value?p->value:"", p->domain?p->domain:"", p->path?p->path:"", p->expire, p->secure)); + if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path))) + { q->version = p->version; + q->expire = p->expire; + q->secure = p->secure; + q->env = 1; + } + if (p->name) + SOAP_FREE(p->name); + if (p->value) + SOAP_FREE(p->value); + if (p->domain) + SOAP_FREE(p->domain); + if (p->path) + SOAP_FREE(p->path); + SOAP_FREE(p); + } + if ((p = (struct soap_cookie*)SOAP_MALLOC(sizeof(struct soap_cookie)))) + { p->name = (char*)SOAP_MALLOC(strlen(tmp)+1); + strcpy(p->name, tmp); + s = soap_decode_cookie(tmp, sizeof(tmp), s); + if (*tmp) + { p->value = (char*)SOAP_MALLOC(strlen(tmp)+1); + strcpy(p->value, tmp); + } + else + p->value = NULL; + p->domain = domain; + p->path = path; + p->expire = 0; + p->secure = 0; + p->version = version; + } + } + if (*s == ';') + s++; + } + if (p) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got cookie %s=%s domain=%s path=%s expire=%ld secure=%d\n", p->name, p->value?p->value:"", p->domain?p->domain:"", p->path?p->path:"", p->expire, p->secure)); + if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path))) + { q->version = p->version; + q->expire = p->expire; + q->secure = p->secure; + } + if (p->name) + SOAP_FREE(p->name); + if (p->value) + SOAP_FREE(p->value); + if (p->domain) + SOAP_FREE(p->domain); + if (p->path) + SOAP_FREE(p->path); + SOAP_FREE(p); + } + if (domain) + SOAP_FREE(domain); + if (path) + SOAP_FREE(path); +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getenv_cookies(struct soap *soap) +{ struct soap_cookie *p; + const char *s; + char key[4096], val[4096]; /* cookie size is up to 4096 bytes [RFC2109] */ + if (!(s = getenv("HTTP_COOKIE"))) + return SOAP_ERR; + do + { s = soap_decode_cookie(key, sizeof(key), s); + s = soap_decode_cookie(val, sizeof(val), s); + p = soap_set_cookie(soap, key, val, NULL, NULL); + if (p) + p->env = 1; + if (*s == ';') + s++; + } while (*s); + return SOAP_OK; +} + +/******************************************************************************/ +SOAP_FMAC1 +struct soap_cookie* +SOAP_FMAC2 +soap_copy_cookies(struct soap *soap) +{ struct soap_cookie *p, **q, *r; + q = &r; + for (p = soap->cookies; p; p = p->next) + { if (!(*q = (struct soap_cookie*)SOAP_MALLOC(sizeof(struct soap_cookie)))) + return r; + **q = *p; + if (p->name) + { if (((*q)->name = (char*)SOAP_MALLOC(strlen(p->name)+1))) + strcpy((*q)->name, p->name); + } + if (p->value) + { if (((*q)->value = (char*)SOAP_MALLOC(strlen(p->value)+1))) + strcpy((*q)->value, p->value); + } + if (p->domain) + { if (((*q)->domain = (char*)SOAP_MALLOC(strlen(p->domain)+1))) + strcpy((*q)->domain, p->domain); + } + if (p->path) + { if (((*q)->path = (char*)SOAP_MALLOC(strlen(p->path)+1))) + strcpy((*q)->path, p->path); + } + q = &(*q)->next; + } + *q = NULL; + return r; +} + +/******************************************************************************/ +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_free_cookies(struct soap *soap) +{ struct soap_cookie *p; + for (p = soap->cookies; p; p = soap->cookies) + { soap->cookies = p->next; + SOAP_FREE(p->name); + if (p->value) + SOAP_FREE(p->value); + if (p->domain) + SOAP_FREE(p->domain); + if (p->path) + SOAP_FREE(p->path); + SOAP_FREE(p); + } +} + +/******************************************************************************/ +#endif /* WITH_COOKIES */ + +/******************************************************************************/ +#ifdef WITH_GZIP +#ifndef PALM_2 +static int +soap_getgzipheader(struct soap *soap) +{ int i; + wchar c, f = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get gzip header\n")); + for (i = 0; i < 9; i++) + { if ((int)(c = soap_get1(soap) == EOF)) + return soap->error = SOAP_EOF; + if (i == 2) + f = c; + } + if (f & 0x04) /* FEXTRA */ + { for (i = soap_get1(soap) | (soap_get1(soap) << 8); i; i--) + if ((int)soap_get1(soap) == EOF) + return soap->error = SOAP_EOF; + } + if (f & 0x08) /* FNAME */ + do + c = soap_get1(soap); + while (c && (int)c != EOF); + if ((int)c != EOF && (f & 0x10)) /* FCOMMENT */ + do + c = soap_get1(soap); + while (c && (int)f != EOF); + if ((int)c != EOF && (f & 0x01)) /* FHCRC */ + { if ((int)(c = soap_get1(soap)) != EOF) + c = soap_get1(soap); + } + if ((int)c == EOF) + return soap->error = SOAP_EOF; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_begin_recv(struct soap *soap) +{ wchar c; + soap_set_local_namespaces(soap); + soap->version = 0; /* don't assume we're parsing SOAP content by default */ + soap_free_iht(soap); + if ((soap->imode & SOAP_IO) == SOAP_IO_CHUNK) + soap->omode |= SOAP_IO_CHUNK; + soap->imode &= ~SOAP_IO; + soap->mode = soap->imode; + if (!soap->keep_alive) + { soap->buflen = 0; + soap->bufidx = 0; + } + if (!(soap->mode & SOAP_IO_KEEPALIVE)) + soap->keep_alive = 0; + soap->ahead = 0; + soap->peeked = 0; + soap->level = 0; + soap->part = SOAP_BEGIN; + soap->alloced = 0; + soap->count = 0; + soap->length = 0; + soap->cdata = 0; + *soap->endpoint = '\0'; + soap->userid = NULL; + soap->passwd = NULL; + soap->action = NULL; + soap->dime_chunksize = 0; + soap->dime_buflen = 0; +#ifdef WIN32 +#ifndef UNDER_CE +#ifndef WITH_FASTCGI + if (!soap_valid_socket(soap->socket)) +#ifdef __BORLANDC__ + setmode((SOAP_SOCKET)soap->recvfd, O_BINARY); +#else + _setmode((SOAP_SOCKET)soap->recvfd, _O_BINARY); +#endif +#endif +#endif +#endif +#ifdef WITH_ZLIB + soap->mode &= ~SOAP_ENC_ZLIB; + soap->zlib_in = SOAP_ZLIB_NONE; + soap->zlib_out = SOAP_ZLIB_NONE; + soap->d_stream.next_in = Z_NULL; + soap->d_stream.avail_in = 0; + soap->d_stream.next_out = (Byte*)soap->buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + soap->z_ratio_in = 1.0; +#endif + c = soap_getchar(soap); + if ((c & 0xFFFC) == (SOAP_DIME_VERSION | SOAP_DIME_MB) && (soap_get0(soap) & 0xFFF0) == 0x20) + soap->mode |= SOAP_ENC_DIME; +#ifdef WITH_GZIP + else if (c == 0x1F) + { if (soap_getgzipheader(soap)) + return soap->error; + if (inflateInit2(&soap->d_stream, -MAX_WBITS) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; + soap->zlib_state = SOAP_ZLIB_INFLATE; + soap->mode |= SOAP_ENC_ZLIB; + soap->zlib_in = SOAP_ZLIB_GZIP; + soap->z_crc = crc32(0L, NULL, 0); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n")); + memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); + /* should not chunk over plain transport, so why bother to check? */ + /* if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) */ + /* soap->z_buflen = soap->bufidx; */ + /* else */ + soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx); + soap->d_stream.avail_in = soap->buflen - soap->bufidx; + soap->z_buflen = soap->buflen; + soap->buflen = soap->bufidx; + } +#endif + else + { if (c == 0xEF && !(soap->mode & SOAP_C_LATIN)) + { soap_unget(soap, c); + c = soap_getutf8(soap); + if (c == 0xFEFF) + c = soap_getchar(soap); + } + while (soap_blank(c)) + c = soap_getchar(soap); + } + if ((int)c == EOF) + return soap->error = SOAP_EOF; + soap_unget(soap, c); + if (c != '<' && !(soap->mode & (SOAP_ENC_DIME | SOAP_ENC_ZLIB))) + { soap->mode &= ~SOAP_IO; + if ((soap->error = soap->fparse(soap))) + { if (soap->error == 307) /* HTTP redirect */ + { soap_getline(soap, soap->endpoint, sizeof(soap->endpoint)); + soap->keep_alive = 0; /* force close when soap_closesock() */ + } + return soap->error; + } + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) + { soap->chunkbuflen = soap->buflen; + soap->buflen = soap->bufidx; + soap->chunksize = 0; + } +#ifdef WITH_ZLIB + if (soap->zlib_in) + { /* fparse should not use soap_unget */ +#ifdef WITH_GZIP + c = soap_get1(soap); + if (c == 0x1F) + { if (soap_getgzipheader(soap)) + return soap->error; + if (inflateInit2(&soap->d_stream, -MAX_WBITS) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; + soap->zlib_state = SOAP_ZLIB_INFLATE; + soap->z_crc = crc32(0L, NULL, 0); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n")); + } + else + { soap_revget1(soap); +#else + { +#endif + if (inflateInit(&soap->d_stream) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; + soap->zlib_state = SOAP_ZLIB_INFLATE; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate initialized\n")); + } + soap->mode |= SOAP_ENC_ZLIB; + memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); + soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx); + soap->d_stream.avail_in = soap->buflen - soap->bufidx; + soap->z_buflen = soap->buflen; + soap->buflen = soap->bufidx; + } +#endif + } +#ifndef WITH_LEANER + if (soap->mode & SOAP_ENC_DIME) + { if (soap_getdimehdr(soap)) + return soap->error; + if (soap->dime_flags & SOAP_DIME_CF) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked DIME SOAP message\n")); + soap->dime_chunksize = soap->dime_size; + if (soap->buflen - soap->bufidx >= soap->dime_chunksize) + { soap->dime_buflen = soap->buflen; + soap->buflen = soap->bufidx + soap->dime_chunksize; + } + else + soap->dime_chunksize -= soap->buflen - soap->bufidx; + } + soap->count = soap->buflen - soap->bufidx; + } +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +http_parse(struct soap *soap) +{ char header[SOAP_HDRLEN], *s; + unsigned short g = 0, k; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Waiting for response...\n")); + *soap->endpoint = '\0'; + soap->length = 0; + do + { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) + return SOAP_EOF; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP status: %s\n", soap->msgbuf)); + for (;;) + { if (soap_getline(soap, header, SOAP_HDRLEN)) + return SOAP_EOF; + if (!*header) + break; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP header: %s\n", header)); + s = strchr(header, ':'); + if (s) + { *s = '\0'; + do s++; + while (*s && *s <= 32); + if ((soap->error = soap->fparsehdr(soap, header, s))) + return soap->error; + } + } + if ((s = strchr(soap->msgbuf, ' '))) + k = (unsigned short)soap_strtoul(s, NULL, 10); + else + k = 0; + } while (k == 100); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Finished HTTP header parsing\n")); + s = strstr(soap->msgbuf, "HTTP/"); + if (s && s[7] != '1') + { if (soap->keep_alive == 1) + soap->keep_alive = 0; + if (k == 0 && (soap->omode & SOAP_IO) == SOAP_IO_CHUNK) /* k == 0 for HTTP request */ + { soap->imode |= SOAP_IO_CHUNK; + soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE; + } + } + if (soap->keep_alive < 0) + soap->keep_alive = 1; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Keep alive connection = %d\n", soap->keep_alive)); + if (s && (((g = !strncmp(soap->msgbuf, "GET ", 4))) || !strncmp(soap->msgbuf, "POST ", 5))) + { size_t m = strlen(soap->endpoint); + size_t n = m + (s - soap->msgbuf) - 5 - (!g); + if (n >= sizeof(soap->endpoint)) + n = sizeof(soap->endpoint) - 1; + strncpy(soap->path, soap->msgbuf + 4 + (!g), n - m); + soap->path[n - m] = '\0'; + strcat(soap->endpoint, soap->path); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Target endpoint='%s'\n", soap->endpoint)); + if (g) + { soap->error = soap->fget(soap); + if (soap->error == SOAP_OK) + soap->error = SOAP_STOP; /* prevents further processing */ + return soap->error; + } + return SOAP_OK; + } + if (k == 0 || (k >= 200 && k <= 299) || k == 400 || k == 500) + return SOAP_OK; + return soap_set_receiver_error(soap, "HTTP error", soap->msgbuf, k); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +http_parse_header(struct soap *soap, const char *key, const char *val) +{ if (!soap_tag_cmp(key, "Host")) + { +#ifdef WITH_OPENSSL + if (soap->imode & SOAP_ENC_SSL) + strcpy(soap->endpoint, "https://"); + else +#endif + strcpy(soap->endpoint, "http://"); + strncat(soap->endpoint, val, sizeof(soap->endpoint) - 8); + soap->endpoint[sizeof(soap->endpoint) - 1] = '\0'; + } + else if (!soap_tag_cmp(key, "Content-Type")) + { if (!soap_tag_cmp(val, "*application/dime*")) + soap->mode |= SOAP_ENC_DIME; + } + else if (!soap_tag_cmp(key, "Content-Length")) + soap->length = soap_strtoul(val, NULL, 10); + else if (!soap_tag_cmp(key, "Content-Encoding")) + { if (!soap_tag_cmp(val, "deflate*")) +#ifdef WITH_ZLIB + soap->zlib_in = SOAP_ZLIB_DEFLATE; +#else + return SOAP_ZLIB_ERROR; +#endif + else if (!soap_tag_cmp(val, "gzip*")) +#ifdef WITH_GZIP + soap->zlib_in = SOAP_ZLIB_GZIP; +#else + return SOAP_ZLIB_ERROR; +#endif + } +#ifdef WITH_ZLIB + else if (!soap_tag_cmp(key, "Accept-Encoding")) + { +#ifdef WITH_GZIP + if (strchr(val, '*') || !soap_tag_cmp(val, "*gzip*")) + soap->zlib_out = SOAP_ZLIB_GZIP; + else +#endif + if (strchr(val, '*') || !soap_tag_cmp(val, "*deflate*")) + soap->zlib_out = SOAP_ZLIB_DEFLATE; + else + soap->zlib_out = SOAP_ZLIB_NONE; + } +#endif + else if (!soap_tag_cmp(key, "Transfer-Encoding")) + { soap->mode &= ~SOAP_IO; + if (!soap_tag_cmp(val, "chunked*")) + soap->mode |= SOAP_IO_CHUNK; + } + else if (!soap_tag_cmp(key, "Connection")) + { if (!soap_tag_cmp(val, "keep-alive*")) + soap->keep_alive = -soap->keep_alive; + else if (!soap_tag_cmp(val, "close*")) + soap->keep_alive = 0; + } +#ifndef WITH_LEAN + else if (!soap_tag_cmp(key, "Authorization")) + { if (!soap_tag_cmp(val, "basic *")) + { size_t n; + char *s; + soap_base642s(soap, val + 6, soap->tmpbuf, sizeof(soap->tmpbuf) - 1, &n); + soap->tmpbuf[n] = '\0'; + if ((s = strchr(soap->tmpbuf, ':'))) + { *s = '\0'; + soap->userid = soap_strdup(soap, soap->tmpbuf); + soap->passwd = soap_strdup(soap, s + 1); + } + } + } +#endif + else if (!soap_tag_cmp(key, "SOAPAction")) + { if (val[0] && val[1]) + { soap->action = soap_strdup(soap, val + 1); + soap->action[strlen(soap->action) - 1] = '\0'; + } + } +/* [ Deal with .NET bug (invalid XML id-ref) */ + else if (!soap_tag_cmp(key, "Server")) + { if (!soap_tag_cmp(val, "Microsoft-IIS*")) + soap->dot_net_bug = 1; + } + else if (!soap_tag_cmp(key, "User-Agent")) + { if (!soap_tag_cmp(val, "*.NET CLR*") || !soap_tag_cmp(val, "*MS Web Services Client Protocol*")) + soap->dot_net_bug = 1; + } +/* ] */ +#ifdef WITH_COOKIES + else if (!soap_tag_cmp(key, "Cookie") || !soap_tag_cmp(key, "Set-Cookie")) + soap_getcookies(soap, val); +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_envelope_begin_out(struct soap *soap) +{ soap->part = SOAP_IN_ENVELOPE; + return soap_element_begin_out(soap, "SOAP-ENV:Envelope", 0, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_envelope_end_out(struct soap *soap) +{ if (soap_element_end_out(soap, "SOAP-ENV:Envelope")) + return soap->error; + soap->part = SOAP_END_ENVELOPE; +#ifndef WITH_LEANER + if (!(soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME)) + return soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->count&3); +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_envelope_begin_in(struct soap *soap) +{ soap->part = SOAP_IN_ENVELOPE; + if (soap_element_begin_in(soap, "SOAP-ENV:Envelope")) + return soap->error = SOAP_VERSIONMISMATCH; + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_envelope_end_in(struct soap *soap) +{ if (soap_element_end_in(soap, "SOAP-ENV:Envelope")) + return soap->error; + soap->part = SOAP_END_ENVELOPE; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_body_begin_out(struct soap *soap) +{ soap->part = SOAP_IN_BODY; + if (soap->version == 1) + soap->encoding = 1; + if (soap_element(soap, "SOAP-ENV:Body", 0, NULL)) + return soap->error; + if (soap_attribute(soap, "id", "_0")) + return soap->error; + return soap_element_start_end_out(soap, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_body_end_out(struct soap *soap) +{ if (soap_element_end_out(soap, "SOAP-ENV:Body")) + return soap->error; + soap->part = SOAP_IN_BODY; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_body_begin_in(struct soap *soap) +{ soap->part = SOAP_IN_BODY; + return soap_element_begin_in(soap, "SOAP-ENV:Body"); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_body_end_in(struct soap *soap) +{ if (soap_element_end_in(soap, "SOAP-ENV:Body")) + return soap->error; + soap->part = SOAP_END_BODY; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv_header(struct soap *soap) +{ if (soap_getheader(soap) && soap->error == SOAP_TAG_MISMATCH) + soap->error = SOAP_OK; + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_endpoint(struct soap *soap, const char *endpoint) +{ register const char *s; + register size_t i, n; + *soap->endpoint = '\0'; + *soap->host = '\0'; + *soap->path = '\0'; + soap->port = 80; + if (!endpoint || !*endpoint) + return; +#ifdef WITH_OPENSSL + if (!strncmp(endpoint, "https:", 6)) + soap->port = 443; +#endif + strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint) - 1); + s = strchr(endpoint, ':'); + if (s && s[1] == '/' && s[2] == '/') + s += 3; + else + s = endpoint; + n = strlen(s); + if (n >= sizeof(soap->host)) + n = sizeof(soap->host) - 1; +/* WR[ */ +#ifdef WITH_IPV6 + if ('[' == s[0]) + { + s++; + for (i = 0; i < n; i++) + { soap->host[i] = s[i]; + if (']' == s[i]) + { + s++; + break; + } + } + } + else + { + for (i = 0; i < n; i++) + { soap->host[i] = s[i]; + if (s[i] == '/' || s[i] == ':') + break; + } + } +#else /* WITH_IPV6 */ +/* ]WR */ + for (i = 0; i < n; i++) + { soap->host[i] = s[i]; + if (s[i] == '/' || s[i] == ':') + break; + } +/* WR[ */ +#endif /* WITH_IPV6 */ +/* ]WR */ + soap->host[i] = '\0'; + if (s[i] == ':') + { soap->port = (int)atol(s + i + 1); + for (i++; i < n; i++) + if (s[i] == '/') + break; + } + if (s[i]) + { strncpy(soap->path, s + i + 1, sizeof(soap->path)); + soap->path[sizeof(soap->path) - 1] = '\0'; + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_connect(struct soap *soap, const char *endpoint, const char *action) +{ return soap_connect_command(soap, SOAP_POST, endpoint, action); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_connect_command(struct soap *soap, int http_command, const char *endpoint, const char *action) +{ char host[sizeof(soap->host)]; + int port; + size_t count; + strcpy(host, soap->host); /* save to compare */ + port = soap->port; /* save to compare */ + soap_set_endpoint(soap, endpoint); + if (action) + soap->action = soap_strdup(soap, action); + if (soap->fconnect) + { + if ((soap->error = soap->fconnect(soap, endpoint, soap->host, soap->port))) + return soap->error; + } + else if (*soap->host) + { soap->status = http_command; + if (!soap_valid_socket(soap->socket) || strcmp(soap->host, host) || soap->port != port) + { soap->keep_alive = 0; /* force close */ + soap_closesock(soap); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Connect to host='%s' path='%s' port=%d\n", soap->host, soap->path, soap->port)); + soap->socket = soap->fopen(soap, endpoint, soap->host, soap->port); + if (soap->error) + return soap->error; + soap->keep_alive = ((soap->omode & SOAP_IO_KEEPALIVE) != 0); + } + else if (!soap->keep_alive || soap_poll(soap)) + { soap->keep_alive = 0; /* force close */ + soap_closesock(soap); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reconnect to host='%s' path='%s' port=%d\n", soap->host, soap->path, soap->port)); + soap->socket = soap->fopen(soap, endpoint, soap->host, soap->port); + if (soap->error) + return soap->error; + } + } + count = soap_begin_dime(soap); + if (soap_begin_send(soap)) + return soap->error; + if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML) && endpoint) + { unsigned int k = soap->mode; + soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB); + if ((k & SOAP_IO) != SOAP_IO_FLUSH) + soap->mode |= SOAP_IO_BUFFER; + if ((soap->error = soap->fpost(soap, endpoint, soap->host, soap->port, soap->path, action, count))) + return soap->error; + if ((k & SOAP_IO) == SOAP_IO_CHUNK) + { if (soap_flush(soap)) + return soap->error; + } + soap->mode = k; + } + if (http_command != SOAP_POST) + return soap_end_send(soap); +#ifndef WITH_LEANER + if (soap->mode & SOAP_ENC_DIME) + return soap_putdimehdr(soap); +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2base64(struct soap *soap, const unsigned char *s, char *t, size_t n) +{ register size_t i; + register unsigned long m; + if (!t) + return SOAP_EOM; + t[0] = '\0'; + if (!s) + return SOAP_OK; + for (; n > 2; n -= 3, s += 3) + { m = ((unsigned long)((unsigned char*)s)[0] << 16) | ((unsigned long)((unsigned char*)s)[1] << 8) | (unsigned long)((unsigned char*)s)[2]; + for (i = 4; i > 0; m >>= 6) + t[--i] = soap_base64o[m & 0x3F]; + t += 4; + } + t[0] = '\0'; + if (n > 0) + { m = 0; + for (i = 0; i < n; i++) + m = (m << 8) | *s++; + for (; i < 3; i++) + m <<= 8; + for (i++; i > 0; m >>= 6) + t[--i] = soap_base64o[m & 0x3F]; + for (i = 3; i > n; i--) + t[i] = '='; + t[4] = '\0'; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_base642s(struct soap *soap, const char *s, char *t, size_t l, size_t *n) +{ register int i, j, c; + register unsigned long m; + char *p = t; + if (n) + *n = 0; + for (;;) + { for (i = 0; i < SOAP_BLKLEN; i++) + { m = 0; + j = 0; + while (j < 4) + { c = *s++; + if (c == '=' || !c) + { i *= 3; + switch (j) + { case 2: + *t++ = (char)((m >> 4) & 0xFF); + i++; + break; + case 3: + *t++ = (char)((m >> 10) & 0xFF); + *t++ = (char)((m >> 2) & 0xFF); + i += 2; + } + if (n) + *n += i; + return p; + } + c -= '+'; + if (c >= 0 && c <= 79) + { m = (m << 6) + soap_base64i[c]; + j++; + } + } + *t++ = (char)((m >> 16) & 0xFF); + *t++ = (char)((m >> 8) & 0xFF); + *t++ = (char)(m & 0xFF); + if (l < 3) + { if (n) + *n += i; + return p; + } + l -= 3; + } + if (n) + *n += 3 * SOAP_BLKLEN; + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_puthttphdr(struct soap *soap, int status, size_t count) +{ const char *s; + if (status == SOAP_FILE) + s = soap->http_content; + else if (status == SOAP_HTML) + s = "text/html; charset=utf-8"; + else if (soap->mode & SOAP_ENC_DIME) + s = "application/dime"; + else if (soap->version == 2) + s = "application/soap+xml; charset=utf-8"; + else + s = "text/xml; charset=utf-8"; + soap->error = soap->fposthdr(soap, "Content-Type", s); + if (soap->error) + return soap->error; +#ifdef WITH_ZLIB + if (soap->omode & SOAP_ENC_ZLIB) +#ifdef WITH_GZIP + soap->error = soap->fposthdr(soap, "Content-Encoding", "gzip"); +#else + soap->error = soap->fposthdr(soap, "Content-Encoding", "deflate"); +#endif +#endif + if ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK) + soap->error = soap->fposthdr(soap, "Transfer-Encoding", "chunked"); + else if (count > 0) + { sprintf(soap->tmpbuf, "%lu", (unsigned long)count); + soap->error = soap->fposthdr(soap, "Content-Length", soap->tmpbuf); + } + if (soap->error) + return soap->error; + return soap->error = soap->fposthdr(soap, "Connection", soap->keep_alive ? "keep-alive" : "close"); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +http_get(struct soap *soap) +{ return SOAP_GET_METHOD; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +http_post(struct soap *soap, const char *endpoint, const char *host, int port, const char *path, const char *action, size_t count) +{ const char *s; + if (soap->status == SOAP_GET) + { s = "GET"; + count = 0; + } + else + s = "POST"; +#ifndef PALM + if (!endpoint || (strncmp(endpoint, "http:", 5) && strncmp(endpoint, "https:", 6) && strncmp(endpoint, "httpg:", 6))) +#else + if (!endpoint || (strncmp(endpoint, "http:", 5) && strncmp(endpoint, "https:", 6) && strncmp(endpoint, "httpg:", 6)) && strncmp(endpoint, "_beam:", 6) && strncmp(endpoint, "_local:", 7) && strncmp(endpoint, "_btobex:", 8)) +#endif + return SOAP_OK; + if (soap->proxy_host) + sprintf(soap->tmpbuf, "%s %s HTTP/%s", s, endpoint, soap->http_version); + else + sprintf(soap->tmpbuf, "%s /%s HTTP/%s", s, path, soap->http_version); + if ((soap->error = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return soap->error; + if (port != 80) + sprintf(soap->tmpbuf, "%s:%d", host, port); + else + strcpy(soap->tmpbuf, host); + if ((soap->error = soap->fposthdr(soap, "Host", soap->tmpbuf)) + || (soap->error = soap->fposthdr(soap, "User-Agent", "gSOAP/2.6")) + || (soap->error = soap_puthttphdr(soap, SOAP_OK, count))) + return soap->error; +#ifdef WITH_ZLIB +#ifdef WITH_GZIP + if ((soap->error = soap->fposthdr(soap, "Accept-Encoding", "gzip, deflate"))) +#else + if ((soap->error = soap->fposthdr(soap, "Accept-Encoding", "deflate"))) +#endif + return soap->error; +#endif +#ifndef WITH_LEAN + if (soap->userid && soap->passwd && strlen(soap->userid) + strlen(soap->passwd) < 761) + { sprintf(soap->tmpbuf + 262, "%s:%s", soap->userid, soap->passwd); + strcpy(soap->tmpbuf, "Basic "); + soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, strlen(soap->tmpbuf + 262)); + if ((soap->error = soap->fposthdr(soap, "Authorization", soap->tmpbuf))) + return soap->error; + } + if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761) + { sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd); + strcpy(soap->tmpbuf, "Basic "); + soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, strlen(soap->tmpbuf + 262)); + if ((soap->error = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf))) + return soap->error; + } +#endif +#ifdef WITH_COOKIES +#ifdef WITH_OPENSSL + if (soap_putcookies(soap, host, path, soap->ssl != NULL)) + return soap->error; +#else + if (soap_putcookies(soap, host, path, 0)) + return soap->error; +#endif +#endif + if (action) + { sprintf(soap->tmpbuf, "\"%s\"", action); + if ((soap->error = soap->fposthdr(soap, "SOAPAction", soap->tmpbuf))) + return soap->error; + } + return soap->error = soap->fposthdr(soap, NULL, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +http_post_header(struct soap *soap, const char *key, const char *val) +{ if (key) + { if (soap_send(soap, key)) + return soap->error; + if (val && (soap_send(soap, ": ") || soap_send(soap, val))) + return soap->error; + } + return soap_send(soap, "\r\n"); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +http_response(struct soap *soap, int status, size_t count) +{ +/* WR[ */ +#ifdef WMW_RPM_IO + if (soap->rpmreqid) + { + httpOutputEnable(soap->rpmreqid); + } +#endif /* WMW_RPM_IO */ +/* ]WR */ + if (!status || status == SOAP_HTML || status == SOAP_FILE) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "OK 200\n")); +/* WR[ */ +#ifdef WMW_RPM_IO + if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */ +#else +/* ]WR */ + if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application */ +/* WR[ */ +#endif /* WMW_RPM_IO */ +/* ]WR */ + { sprintf(soap->tmpbuf, "HTTP/%s 200 OK", soap->http_version); + if ((soap->error = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return soap->error; + } + else if ((soap->error = soap->fposthdr(soap, "Status", "200 OK"))) + return soap->error; + } + else if (status > 200 && status < 600) + { sprintf(soap->tmpbuf, "HTTP/%s %d %s", soap->http_version, status, http_error(soap, status)); + if ((soap->error = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return soap->error; + if (status == 401) + if ((soap->error = soap->fposthdr(soap, "WWW-Authenticate", "Basic realm=\"gSOAP Service\""))) + return soap->error; + } + else + { const char *s = *soap_faultcode(soap); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error\n")); + if (soap->version == 2 && !strcmp(s, "SOAP-ENV:Sender")) + s = "400 Bad Request"; + else + s = "500 Internal Server Error"; +/* WR[ */ +#ifdef WMW_RPM_IO + if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */ +#else +/* ]WR */ + if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application */ +/* WR[ */ +#endif /* WMW_RPM_IO */ +/* ]WR */ + { sprintf(soap->tmpbuf, "HTTP/%s %s", soap->http_version, s); + if ((soap->error = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return soap->error; + } + else if ((soap->error = soap->fposthdr(soap, "Status", s))) + return soap->error; + } + if ((soap->error = soap->fposthdr(soap, "Server", "gSOAP/2.6")) + || (soap->error = soap_puthttphdr(soap, status, count))) + return soap->error; +#ifdef WITH_COOKIES + if (soap_putsetcookies(soap)) + return soap->error; +#endif + return soap->error = soap->fposthdr(soap, NULL, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_response(struct soap *soap, int status) +{ register size_t count; + if (!(soap->omode & (SOAP_ENC_XML | SOAP_IO_STORE /* this tests for chunking too */)) + && (status == SOAP_HTML || status == SOAP_FILE)) + { soap->omode &= ~SOAP_IO; + soap->omode |= SOAP_IO_STORE; + } + soap->status = status; + count = soap_begin_dime(soap); + if (soap_begin_send(soap)) + return soap->error; + if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML)) + { register int n = soap->mode; + soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB); + if ((n & SOAP_IO) != SOAP_IO_FLUSH) + soap->mode |= SOAP_IO_BUFFER; + if ((soap->error = soap->fresponse(soap, status, count))) + return soap->error; + if ((n & SOAP_IO) == SOAP_IO_CHUNK) + { if (soap_flush(soap)) + return soap->error; + } + soap->mode = n; + } +#ifndef WITH_LEANER + if (soap->mode & SOAP_ENC_DIME) + return soap_putdimehdr(soap); +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_fault(struct soap *soap) +{ const char **c = soap_faultcode(soap); + const char **s = soap_faultstring(soap); + if (!*c) + { if (soap->version == 2) + *c = "SOAP-ENV:Sender"; + else + *c = "SOAP-ENV:Client"; + } + if (*s) + return; + switch (soap->error) + { case SOAP_CLI_FAULT: + *s = "Client fault"; + break; + case SOAP_SVR_FAULT: + *s = "Server fault"; + break; + case SOAP_TAG_MISMATCH: + sprintf(soap->msgbuf, "Tag mismatch: element '%s' does not correspond to expected element", soap->tag); + *s = soap->msgbuf; + break; + case SOAP_TYPE: + sprintf(soap->msgbuf, "Data type '%s' mismatch in element '%s'", soap->type, soap->tag); + *s = soap->msgbuf; + break; + case SOAP_SYNTAX_ERROR: + *s = "XML syntax error"; + break; + case SOAP_NO_TAG: + *s = "No XML element tag found"; + break; + case SOAP_MUSTUNDERSTAND: + *c = "SOAP-ENV:MustUnderstand"; + sprintf(soap->msgbuf, "The data in element '%s' must be understood but cannot be handled", soap->tag); + *s = soap->msgbuf; + break; + case SOAP_VERSIONMISMATCH: + *c = "SOAP-ENV:VersionMismatch"; + *s = "SOAP version mismatch or invalid SOAP message"; + break; + case SOAP_DATAENCODINGUNKNOWN: + *c = "SOAP-ENV:DataEncodingUnknown"; + *s = "Unsupported SOAP data encoding"; + break; + case SOAP_DIME_MISMATCH: + *s = "DIME version mismatch"; + break; + case SOAP_NAMESPACE: + sprintf(soap->msgbuf, "Namespace URI mismatch in element '%s'", soap->tag); + *s = soap->msgbuf; + break; + case SOAP_OBJ_MISMATCH: + *s = "Object mismatch"; + break; + case SOAP_FATAL_ERROR: + *s = "Fatal error"; + break; + case SOAP_NO_METHOD: + sprintf(soap->msgbuf, "Method '%s' not implemented", soap->tag); + *s = soap->msgbuf; + break; + case SOAP_GET_METHOD: + *s = "HTTP GET method not implemented"; + break; + case SOAP_EOM: + *s = "Out of memory"; + break; + case SOAP_IOB: + *s = "Array index out of bounds"; + break; + case SOAP_NULL: + sprintf(soap->msgbuf, "Cannot create nilable object for type '%s' in element '%s'", soap->type, soap->tag); + *s = soap->msgbuf; + break; + case SOAP_MULTI_ID: + *s = "Non-unique id attribute"; + break; + case SOAP_MISSING_ID: + *s = "Missing id: referenced data is missing or had to be ignored"; + break; + case SOAP_HREF: + *s = "Invalid XML: object reference with href attribute is incompatible with actual object referred to"; + break; + case SOAP_FAULT: + break; + case SOAP_TCP_ERROR: + *s = tcp_error(soap); + break; + case SOAP_HTTP_ERROR: + *s = "HTTP error"; + break; + case SOAP_SSL_ERROR: + *s = "SSL error"; + break; + case SOAP_PLUGIN_ERROR: + *s = "Plugin registry error"; + break; + case SOAP_DIME_ERROR: + *s = "DIME error"; + break; + case SOAP_ZLIB_ERROR: +#ifdef WITH_ZLIB + sprintf(soap->msgbuf, "Zlib/gzip error: '%s'", soap->d_stream.msg?soap->d_stream.msg:""); + *s = soap->msgbuf; +#else + *s = "Zlib not installed for required message (de)compression"; +#endif + break; + case SOAP_EOD: + *s = "End of DIME error"; + break; + case SOAP_REQUIRED: + *s = "Validation failure: XML attribute required"; + break; + case SOAP_OCCURS: + *s = "Validation failure: XML element occurs count"; + break; + case SOAP_EOF: + sprintf(soap->msgbuf, "End of file or no input: '%s'", soap_strerror(soap)); + *s = soap->msgbuf; + break; + default: + if (soap->error > 200 && soap->error < 600) + { sprintf(soap->msgbuf, "HTTP Error: '%s'", http_error(soap, soap->error)); + *s = soap->msgbuf; + } + else + *s = "Unknown error code"; + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send_fault(struct soap *soap) +{ register int status = soap->error; + if (status == SOAP_STOP) + return status; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Sending back fault struct for error code %d\n", soap->error)); + soap->keep_alive = 0; /* to terminate connection */ + soap_set_fault(soap); + if ((status != SOAP_EOF || (!soap->recv_timeout && !soap->send_timeout)) && soap_poll(soap) == SOAP_OK) + { soap->error = SOAP_OK; + soap_serializeheader(soap); + soap_serializefault(soap); + soap_begin_count(soap); + if (soap->mode & SOAP_IO_LENGTH) + { soap_envelope_begin_out(soap); + soap_putheader(soap); + soap_body_begin_out(soap); + soap_putfault(soap); + soap_body_end_out(soap); + soap_envelope_end_out(soap); + } + if (soap_response(soap, status) + || soap_envelope_begin_out(soap) + || soap_putheader(soap) + || soap_body_begin_out(soap) + || soap_putfault(soap) + || soap_body_end_out(soap) + || soap_envelope_end_out(soap)) + return soap_closesock(soap); + soap_end_send(soap); + } + soap_closesock(soap); + return soap->error = status; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv_fault(struct soap *soap) +{ register int status = soap->error; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Receiving SOAP Fault\n")); + soap->error = SOAP_OK; + if (soap_getfault(soap)) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Error: soap_get_soapfault() failed. Is this a SOAP message at all?\n")); + *soap_faultcode(soap) = (soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client"); + soap->error = status; + soap_set_fault(soap); + } + else + { register const char *s = *soap_faultcode(soap); + if (!soap_match_tag(soap, s, "SOAP-ENV:Server") || !soap_match_tag(soap, s, "SOAP-ENV:Receiver")) + status = SOAP_SVR_FAULT; + else if (!soap_match_tag(soap, s, "SOAP-ENV:Client") || !soap_match_tag(soap, s, "SOAP-ENV:Sender")) + status = SOAP_CLI_FAULT; + else if (!soap_match_tag(soap, s, "SOAP-ENV:MustUnderstand")) + status = SOAP_MUSTUNDERSTAND; + else if (!soap_match_tag(soap, s, "SOAP-ENV:VersionMismatch")) + status = SOAP_VERSIONMISMATCH; + else + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Fault code %s\n", s)); + status = SOAP_FAULT; + } + if (soap_body_end_in(soap) + || soap_envelope_end_in(soap) + || soap_end_recv(soap)) + return soap_closesock(soap); + soap->error = status; + } + return soap_closesock(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static const char* +soap_strerror(struct soap *soap) +{ int err = soap->errnum; + if (!err) + err = soap_errno; + if (err) + { +#ifndef UNDER_CE + return strerror(err); +#else + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0, (LPTSTR)&soap->werrorstr, 256, NULL); + wcstombs(soap->errorstr, soap->werrorstr, 256); + return soap->errorstr; +#endif + } + return "Operation interrupted or timed out"; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +soap_set_error(struct soap *soap, const char *faultcode, const char *faultstring, const char *faultdetail, int soaperror) +{ *soap_faultcode(soap) = faultcode; + *soap_faultstring(soap) = faultstring; + if (faultdetail && *faultdetail) + { register const char **s = soap_faultdetail(soap); + if (s) + *s = faultdetail; + } + return soap->error = soaperror; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_sender_error(struct soap *soap, const char *faultstring, const char *faultdetail, int soaperror) +{ return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", faultstring, faultdetail, soaperror); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_receiver_error(struct soap *soap, const char *faultstring, const char *faultdetail, int soaperror) +{ return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", faultstring, faultdetail, soaperror); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +soap_copy_fault(struct soap *soap, const char *faultcode, const char *faultstring, const char *faultdetail) +{ char *s = NULL, *t = NULL; + if (faultstring) + s = soap_strdup(soap, faultstring); + if (faultdetail) + t = soap_strdup(soap, faultdetail); + return soap_set_error(soap, faultcode, s, t, SOAP_FAULT); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_sender_fault(struct soap *soap, const char *faultstring, const char *faultdetail) +{ return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", faultstring, faultdetail); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_receiver_fault(struct soap *soap, const char *faultstring, const char *faultdetail) +{ return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", faultstring, faultdetail); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_print_fault(struct soap *soap, FILE *fd) +{ if (soap->error) + { const char **s; + if (!*soap_faultcode(soap)) + soap_set_fault(soap); + fprintf(fd, "SOAP FAULT: %s\n\"%s\"\n", *soap_faultcode(soap), *soap_faultstring(soap)); + s = soap_faultdetail(soap); + if (s && *s) + fprintf(fd, "Detail: %s\n", *s); + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_print_fault_location(struct soap *soap, FILE *fd) +{ +#ifndef WITH_LEAN + int c; + if (soap->error && soap->buflen > 0) + { if (soap->bufidx == 0) + soap->bufidx = 1; + c = soap->buf[soap->bufidx - 1]; + soap->buf[soap->bufidx - 1] = '\0'; + soap->buf[soap->buflen - 1] = '\0'; + if (soap->bufidx < soap->buflen) + fprintf(fd, "%s%c\n** HERE **\n%s\n", soap->buf, c, soap->buf + soap->bufidx); + else + fprintf(fd, "%s%c\n** HERE **\n", soap->buf, c); + } +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_register_plugin_arg(struct soap *soap, int (*fcreate)(struct soap*, struct soap_plugin*, void*), void *arg) +{ register struct soap_plugin *p; + register int r; + if (!(p = (struct soap_plugin*)SOAP_MALLOC(sizeof(struct soap_plugin)))) + return soap->error = SOAP_EOM; + p->id = NULL; + p->data = NULL; + p->fcopy = NULL; + p->fdelete = NULL; + r = fcreate(soap, p, arg); + if (!r && p->fdelete) + { p->next = soap->plugins; + soap->plugins = p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Registered '%s' plugin\n", p->id)); + return SOAP_OK; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not register plugin '%s': plugin returned error %d (or fdelete callback not set)\n", p->id?p->id:"?", r)); + SOAP_FREE(p); + return r; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static void * +fplugin(struct soap *soap, const char *id) +{ register struct soap_plugin *p; + for (p = soap->plugins; p; p = p->next) + if (p->id == id || !strcmp(p->id, id)) + return p->data; + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void * +SOAP_FMAC2 +soap_lookup_plugin(struct soap *soap, const char *id) +{ return soap->fplugin(soap, id); +} +#endif + +/******************************************************************************/ +#ifdef __cplusplus +} +#endif + diff --git a/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.6.2.h b/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.6.2.h new file mode 100644 index 0000000..15a47fa --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.6.2.h @@ -0,0 +1,1647 @@ +/* + +stdsoap2.h 2.6.2 + +Runtime environment. + +gSOAP XML Web services tools +Copyright (C) 2000-2004, Robert van Engelen, Genivia, Inc. All Rights Reserved. + +Contributors: + +Wind River Systems, Inc., for the following additions (marked WR[...]) : + - vxWorks compatible + - Support for IPv6. + +-------------------------------------------------------------------------------- +gSOAP public license. + +The contents of this file are subject to the gSOAP Public License Version 1.3 +(the "License"); you may not use this file except in compliance with the +License. You may obtain a copy of the License at +http://www.cs.fsu.edu/~engelen/soaplicense.html +Software distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +for the specific language governing rights and limitations under the License. + +The Initial Developer of the Original Code is Robert A. van Engelen. +Copyright (C) 2000-2004 Robert A. van Engelen, Genivia inc. All Rights Reserved. +-------------------------------------------------------------------------------- +GPL license. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA + +Author contact information: +engelen@genivia.com / engelen@acm.org +-------------------------------------------------------------------------------- +*/ + +#ifdef WITH_SOAPDEFS_H +# include "soapdefs.h" /* include user-defined stuff */ +#endif + +#ifndef _THREAD_SAFE +# define _THREAD_SAFE +#endif + +#ifndef OPENSERVER +# ifndef _REENTRANT +# define _REENTRANT +# endif +#endif + +#ifndef SOAP_BEGIN_NAMESPACE +# define SOAP_BEGIN_NAMESPACE(name) +#endif + +#ifndef SOAP_END_NAMESPACE +# define SOAP_END_NAMESPACE(name) +#endif + +#ifndef SOAP_FMAC1 /* stdsoap2.h declaration macro */ +# define SOAP_FMAC1 +#endif + +#ifndef SOAP_FMAC2 /* stdsoap2.h declaration macro */ +# define SOAP_FMAC2 +#endif + +#ifndef SOAP_FMAC3 /* (de)serializer declaration macro */ +# define SOAP_FMAC3 +#endif + +#ifndef SOAP_FMAC4 /* (de)serializer declaration macro */ +# define SOAP_FMAC4 +#endif + +#ifndef SOAP_FMAC5 /* stub/skeleton declaration macro */ +# define SOAP_FMAC5 +#endif + +#ifndef SOAP_FMAC6 /* stub/skeleton declaration macro */ +# define SOAP_FMAC6 +#endif + +#ifndef SOAP_CMAC /* class declaration macro */ +# define SOAP_CMAC +#endif + +#ifndef SOAP_NMAC /* namespace table declaration macro */ +# define SOAP_NMAC +#endif + +#ifndef SOAP_SOURCE_STAMP +# define SOAP_SOURCE_STAMP(str) +#endif + +#ifdef WITH_LEANER +# ifndef WITH_LEAN +# define WITH_LEAN +# endif +#endif + +#ifdef WITH_LEAN +# ifdef WITH_COOKIES +# error "Cannot build WITH_LEAN code WITH_COOKIES enabled" +# endif +#endif + +#ifndef STDSOAP_H +#define STDSOAP_H + +/* WR[ */ +#if (defined(__vxworks) || defined(__VXWORKS__)) +# define VXWORKS +#endif +/* ]WR */ + +#ifdef _WIN32 +# ifndef WIN32 +# define WIN32 +# endif +#endif + +#ifdef UNDER_CE +# ifndef WIN32 +# define WIN32 +# endif +#endif + +#ifdef __BORLANDC__ +# ifdef __WIN32__ +# ifndef WIN32 +# define WIN32 +# endif +# endif +#endif + +#ifdef __CYGWIN__ +# ifndef CYGWIN +# define CYGWIN +# endif +#endif + +#ifdef __SYMBIAN32__ +# define SYMBIAN +#endif + +#ifdef __palmos__ +# define PALM +#endif + +#ifdef PALM_GCC +# define PALM +#endif + +#ifdef HAVE_CONFIG_H +# include "config.h" +#else +# if defined(UNDER_CE) +# define WITH_LEAN +# elif defined(WIN32) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(CYGWIN) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(__APPLE__) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_TIMEGM +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(_AIXVERSION_431) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(HP_UX) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(FREEBSD) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_GETTIMEOFDAY +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(__VMS) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(__GLIBC__) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_TIMEGM +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(TRU64) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_GETTIMEOFDAY +# define HAVE_SYS_TIMEB_H +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(MAC_CARBON) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GETHOSTBYNAME_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(PALM) +# define HAVE_STRTOD /* strtod() is defined in palmmissing.h */ +# ifndef CONST2 +# define CONST2 +# endif +# define WITH_LEAN +# define WITH_NONAMESPACES +# define _LINUX_CTYPE_H +# include + typedef WChar wchar_t; +# define IGNORE_STDIO_STUBS + typedef Int32 time_t; +# define tm HostTmType +# define strftime HostStrFTime +# define mktime HostMkTime +# define localtime HostLocalTime +# define tm_year tm_year_ +# define tm_hour tm_hour_ +# define tm_mon tm_mon_ +# define tm_min tm_min_ +# define tm_sec tm_sec_ +# define tm_mday tm_mday_ +# define tm_isdst tm_isdst_ +# include +# define O_NONBLOCK FNONBIO +# include +# if 1 + void displayText(char *text); +# define pdebug(s) displayText(s) +# define pdebugV(s,p) sprintf(buff,s,p); displayText(buff) +# else +# define pdebug(s) WinDrawChars(s,strlen(s),10,10) +# define pdebugV(s,p) sprintf(buff,s,p); WinDrawChars(buff,strlen(buff),10,10) +# endif +# include "palmmissing.h" +# include "slib_socket.h" +# elif defined(SYMBIAN) +# define WITH_LEAN +# define WITH_NONAMESPACES +# define CONST2 const +# undef SOAP_FMAC1 +# define SOAP_FMAC1 EXPORT_C +# ifdef __cplusplus +# include +# else +# define TInt64 long +# endif +/* WR[ */ +# elif defined(VXWORKS) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_RAND_R +# define HAVE_PGMTIME_R +# define HAVE_PLOCALTIME_R +# define HAVE_MKTIME +/* ]WR */ +# else +/* Default asumptions on supported functions */ +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GETHOSTBYNAME_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# endif +#endif + +#if defined(TRU64) +# define SOAP_LONG_FORMAT "%ld" +# define SOAP_ULONG_FORMAT "%lu" +#elif defined(WIN32) +# define SOAP_LONG_FORMAT "%I64d" +# define SOAP_ULONG_FORMAT "%I64u" +#endif + +#ifndef SOAP_LONG_FORMAT +# define SOAP_LONG_FORMAT "%lld" /* printf format for 64 bit ints */ +#endif + +#ifndef SOAP_ULONG_FORMAT +# define SOAP_ULONG_FORMAT "%llu" /* printf format for unsigned 64 bit ints */ +#endif + +#ifndef SOAP_MALLOC /* use libc malloc */ +# define SOAP_MALLOC(n) malloc(n) +#endif + +#ifndef SOAP_FREE /* use libc free */ +# define SOAP_FREE(p) free(p) +#endif + +#include + +#ifndef PALM +# include +#endif + +#ifndef PALM_GCC +# include +#endif + +#include /* for tolower() */ +#include + +#if defined(__cplusplus) && !defined(UNDER_CE) +# include +# include + using namespace std; +#endif + +#ifndef UNDER_CE +# ifndef PALM +# include +# ifndef MAC_CARBON +# include +# endif +# ifndef WITH_LEAN +# ifdef HAVE_SYS_TIMEB_H +# include /* for ftime() */ +# endif +# include +# endif +# endif +#endif + +#ifdef OPENSERVER +# include +# include +# include + extern int h_errno; +#endif + +#ifndef MAC_CARBON +# ifndef WIN32 +# ifndef PALM +# include +/* WR[ */ +# ifdef VXWORKS +# include +# endif +# ifndef VXWORKS +/* ]WR */ +# ifndef SYMBIAN +# include +# endif +/* WR[ */ +# endif +/* ]WR */ +# ifdef SUN_OS +# include /* SUN */ +# include /* SUN < 2.8 (?) */ +# endif +/* WR[ */ +# ifdef VXWORKS +# include +# else +/* ]WR */ +# include +/* WR[ */ +# endif +/* ]WR */ +# include +# include /* TCP_NODELAY */ +# include +# endif +# endif +#endif + +#ifdef WITH_FASTCGI +# include +#endif + +#ifdef WITH_OPENSSL +# define OPENSSL_NO_KRB5 +# include +# include +# include +# ifndef ALLOW_OLD_VERSIONS +# if (OPENSSL_VERSION_NUMBER < 0x00905100L) +# error "Must use OpenSSL 0.9.6 or later" +# endif +# endif +#endif + +#ifdef WITH_GZIP +# ifndef WITH_ZLIB +# define WITH_ZLIB +# endif +#endif + +#ifdef WITH_CASEINSENSITIVETAGS +# define SOAP_STRCMP soap_tag_cmp /* case insensitve XML element/attribute names */ +#else +# define SOAP_STRCMP strcmp /* case sensitive XML element/attribute names */ +#endif + +#ifdef WITH_ZLIB +# include +#endif + +#ifndef PALM_GCC +# include /* for isnan() */ +#endif + +/* #define DEBUG */ /* Uncomment to debug sending (in file SENT.log) receiving (in file RECV.log) and messages (in file TEST.log) */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define soap_get0(soap) (((soap)->bufidx>=(soap)->buflen && soap_recv(soap)) ? EOF : (unsigned char)(soap)->buf[(soap)->bufidx]) +#define soap_get1(soap) (((soap)->bufidx>=(soap)->buflen && soap_recv(soap)) ? EOF : (unsigned char)(soap)->buf[(soap)->bufidx++]) +#define soap_revget1(soap) ((soap)->bufidx--) +#define soap_unget(soap, c) ((soap)->ahead = c) +#define soap_register_plugin(soap, plugin) soap_register_plugin_arg(soap, plugin, NULL) +#define soap_imode(soap, n) ((soap)->mode = (soap)->imode = (n)) +#define soap_set_imode(soap, n) ((soap)->mode = (soap)->imode |= (n)) +#define soap_clr_imode(soap, n) ((soap)->mode = (soap)->imode &= ~(n)) +#define soap_omode(soap, n) ((soap)->mode = (soap)->omode = (n)) +#define soap_set_omode(soap, n) ((soap)->mode = (soap)->omode |= (n)) +#define soap_clr_omode(soap, n) ((soap)->mode = (soap)->omode &= ~(n)) +#define soap_destroy(soap) soap_delete((soap), NULL) + +#ifdef WIN32 +# ifndef UNDER_CE +# include +# include +# endif +# include +/* # include */ /* Alternative: use winsock2 (not available with eVC) */ +/* WR[ */ +# ifdef WITH_IPV6 +# include +# include +# endif +#else +# ifdef VXWORKS +# include +# include +# include +# endif +/* ]WR */ +# ifndef MAC_CARBON +# ifndef PALM +# include +# include +# endif +# include +# include +# endif +#endif + +#ifdef WIN32 +# define SOAP_SOCKET SOCKET +#else +# define SOAP_SOCKET int +# define closesocket(n) close(n) +#endif + +#define soap_valid_socket(n) ((n) >= 0) +#define SOAP_INVALID_SOCKET (-1) + +/* WR[ */ +#ifdef VXWORKS +# ifdef __INCmathh +# define _MATH_H +# include +# define isnan(num) isNan(num) +# endif +#endif + +#ifdef WIN32 +# define _MATH_H +# include +# define isnan(num) _isnan(num) +#endif +/* ]WR */ + +#if (!defined(_MATH_H) && !defined(_MATH_INCLUDED)) +# ifndef isnan +# define isnan(_) (0) +# endif +#endif + +extern const struct soap_double_nan { unsigned int n1, n2; } soap_double_nan; + +#if defined(SYMBIAN) +# define LONG64 TInt64 +# define ULONG64 TInt64 +#elif !defined(WIN32) +# define LONG64 long long +# define ULONG64 unsigned LONG64 +#elif defined(UNDER_CE) +# define LONG64 __int64 +# define ULONG64 unsigned LONG64 +#elif defined(__BORLANDC__) +# define LONG64 __int64 +# define ULONG64 unsigned LONG64 +#endif + +#ifdef WIN32 +# define SOAP_EINTR WSAEINTR +# define SOAP_EAGAIN WSAEWOULDBLOCK +# define SOAP_EWOULDBLOCK WSAEWOULDBLOCK +# define SOAP_EINPROGRESS WSAEINPROGRESS +#else +# define SOAP_EINTR EINTR +# define SOAP_EAGAIN EAGAIN +# ifdef SYMBIAN +# define SOAP_EWOULDBLOCK 9898 +# define SOAP_EINPROGRESS 9899 +# else +# define SOAP_EWOULDBLOCK EWOULDBLOCK +# define SOAP_EINPROGRESS EINPROGRESS +# endif +#endif + +#ifdef WIN32 +# ifdef UNDER_CE +# define soap_errno GetLastError() +# define soap_socket_errno GetLastError() +# else +# define soap_errno GetLastError() +# define soap_socket_errno WSAGetLastError() +# endif +#else +# define soap_errno errno +# define soap_socket_errno errno +#endif + +#ifndef SOAP_BUFLEN +# ifndef WITH_LEAN +# define SOAP_BUFLEN (32768) /* buffer length for socket packets, also used by gethostbyname_r so don't make this too small */ +# else +# define SOAP_BUFLEN (2048) +# endif +#endif +#ifndef SOAP_LABLEN +# ifndef WITH_LEAN +# define SOAP_LABLEN (256) /* initial look-aside buffer length */ +# else +# define SOAP_LABLEN (64) +# endif +#endif +#ifndef SOAP_PTRHASH +# ifndef WITH_LEAN +# define SOAP_PTRHASH (1024) /* size of pointer analysis hash table (must be power of 2) */ +# else +# define SOAP_PTRHASH (16) +# endif +#endif +#ifndef SOAP_IDHASH +# ifndef WITH_LEAN +# define SOAP_IDHASH (256) /* size of hash table for receiving id/href's */ +# else +# define SOAP_IDHASH (16) +# endif +#endif +#ifndef SOAP_BLKLEN +# define SOAP_BLKLEN (256) /* size of blocks to collect long strings and XML attributes */ +#endif +#ifndef SOAP_TAGLEN +# define SOAP_TAGLEN (256) /* maximum length of XML element tag/attribute name + 1 */ +#endif +#ifndef SOAP_HDRLEN +# ifndef WITH_LEAN +# define SOAP_HDRLEN (8192) /* maximum length of HTTP header line (must be >4096 to read cookies) */ +# else +# define SOAP_HDRLEN (1024) +# endif +#endif +#ifndef SOAP_MAXDIMS +# define SOAP_MAXDIMS (16) /* maximum array dimensions (array nestings) must be less than 64 to protect soap->tmpbuf */ +#endif + +#ifndef SOAP_MAXLOGS +# define SOAP_MAXLOGS (3) /* max number of debug logs per struct soap environment */ +# define SOAP_INDEX_RECV (0) +# define SOAP_INDEX_SENT (1) +# define SOAP_INDEX_TEST (2) +#endif + +#ifndef SOAP_MAXKEEPALIVE +# define SOAP_MAXKEEPALIVE (100) /* max iterations to keep server connection alive */ +#endif + +#ifndef SOAP_MAXARRAYSIZE +# define SOAP_MAXARRAYSIZE (100000) /* "trusted" max size of inbound SOAP array for compound array allocation */ +#endif + +/* WR[ */ +#ifdef VXWORKS +# ifndef FLT_MAX +# define FLT_MAX _ARCH_FLT_MAX +# endif +# ifndef DBL_MAX +# define DBL_MAX _ARCH_DBL_MAX +# endif +#endif +/* ]WR */ + +#ifndef FLT_NAN +# if (defined(_MATH_H) || defined(_MATH_INCLUDED)) +# define FLT_NAN (*(float*)&soap_double_nan) +# else +# define FLT_NAN (0.0) +# endif +#endif + +#ifndef FLT_PINFTY +# ifdef FLT_MAX +# define FLT_PINFTY FLT_MAX +# else +# ifdef HUGE_VAL +# define FLT_PINFTY (float)HUGE_VAL +# else +# ifdef FLOAT_MAX +# define FLT_PINFTY FLOAT_MAX +# else +# define FLT_PINFTY (3.40282347e+38) +# endif +# endif +# endif +#endif + +#ifndef FLT_NINFTY +# define FLT_NINFTY (-FLT_PINFTY) +#endif + +#ifndef DBL_NAN +# if (defined(_MATH_H) || defined(_MATH_INCLUDED)) +# define DBL_NAN (*(double*)&soap_double_nan) +# else +# define DBL_NAN (0.0) +# endif +#endif +#ifndef DBL_PINFTY +# ifdef DBL_MAX +# define DBL_PINFTY DBL_MAX +# else +# ifdef HUGE_VAL +# define DBL_PINFTY (double)HUGE_VAL +# else +# ifdef DOUBLE_MAX +# define DBL_PINFTY DOUBLE_MAX +# else +# define DBL_PINFTY (1.7976931348623157e+308) +# endif +# endif +# endif +#endif + +#ifndef DBL_NINFTY +# define DBL_NINFTY (-DBL_PINFTY) +#endif + +/* gSOAP error codes */ + +#define SOAP_EOF EOF +#define SOAP_ERR EOF +#define SOAP_OK 0 +#define SOAP_CLI_FAULT 1 +#define SOAP_SVR_FAULT 2 +#define SOAP_TAG_MISMATCH 3 +#define SOAP_TYPE 4 +#define SOAP_SYNTAX_ERROR 5 +#define SOAP_NO_TAG 6 +#define SOAP_IOB 7 +#define SOAP_MUSTUNDERSTAND 8 +#define SOAP_NAMESPACE 9 +#define SOAP_OBJ_MISMATCH 10 +#define SOAP_FATAL_ERROR 11 +#define SOAP_FAULT 12 +#define SOAP_NO_METHOD 13 +#define SOAP_GET_METHOD 14 +#define SOAP_EOM 15 +#define SOAP_NULL 16 +#define SOAP_MULTI_ID 17 +#define SOAP_MISSING_ID 18 +#define SOAP_HREF 19 +#define SOAP_TCP_ERROR 20 +#define SOAP_HTTP_ERROR 21 +#define SOAP_SSL_ERROR 22 +#define SOAP_ZLIB_ERROR 23 +#define SOAP_DIME_ERROR 24 +#define SOAP_EOD 25 +#define SOAP_VERSIONMISMATCH 26 +#define SOAP_DIME_MISMATCH 27 +#define SOAP_PLUGIN_ERROR 28 +#define SOAP_DATAENCODINGUNKNOWN 29 +#define SOAP_REQUIRED 30 +#define SOAP_OCCURS 31 + +#define soap_xml_error_check(e) ((e) == SOAP_TAG_MISMATCH || (e) == SOAP_SYNTAX_ERROR || (e) == SOAP_NAMESPACE || (e) == SOAP_MULTI_ID || (e) == SOAP_MISSING_ID || (e) == SOAP_REQUIRED || (e) == SOAP_OCCURS) +#define soap_soap_error_check(e) ((e) == SOAP_CLI_FAULT || (e) == SOAP_SVR_FAULT || (e) == SOAP_VERSIONMISMATCH || (e) == SOAP_MUSTUNDERSTAND || (e) == SOAP_FAULT || (e) == SOAP_NO_METHOD || (e) == SOAP_OBJ_MISMATCH || (e) == SOAP_NULL) +#define soap_tcp_error_check(e) ((e) == SOAP_EOF || (e) == SOAP_TCP_ERROR) +#define soap_ssl_error_check(e) ((e) == SOAP_SSL_ERROR) +#define soap_zlib_error_check(e) ((e) == SOAP_ZLIB_ERROR) +#define soap_dime_error_check(e) ((e) == SOAP_DIME_ERROR || (e) == SOAP_DIME_MISMATCH) +#define soap_http_error_check(e) ((e) == SOAP_HTTP_ERROR || (e) == SOAP_GET_METHOD || ((e) >= 100 && (e) < 600)) + +/* gSOAP HTTP response status codes 100 to 600 are reserved */ + +/* Special gSOAP HTTP response status codes */ + +#define SOAP_STOP 1000 /* No HTTP response */ +#define SOAP_HTML 1001 /* Custom HTML response */ +#define SOAP_FILE 1002 /* Custom file-based response */ + +/* gSOAP HTTP request status codes */ + +#define SOAP_POST 1003 +#define SOAP_GET 1104 + +/* gSOAP DIME */ + +#define SOAP_DIME_CF 0x01 +#define SOAP_DIME_ME 0x02 +#define SOAP_DIME_MB 0x04 +#define SOAP_DIME_VERSION 0x08 /* DIME version 1 */ +#define SOAP_DIME_MEDIA 0x10 +#define SOAP_DIME_ABSURI 0x20 + +/* gSOAP ZLIB */ + +#define SOAP_ZLIB_NONE 0x00 +#define SOAP_ZLIB_DEFLATE 0x01 +#define SOAP_ZLIB_INFLATE 0x02 +#define SOAP_ZLIB_GZIP 0x02 + +/* gSOAP transport, connection, and content encoding modes */ + +#define SOAP_IO 0x000003 +#define SOAP_IO_FLUSH 0x000000 /* flush output immediately, no buffering */ +#define SOAP_IO_BUFFER 0x000001 /* buffer output in packets of size SOAP_BUFLEN */ +#define SOAP_IO_STORE 0x000002 /* store entire output to determine length for transport */ +#define SOAP_IO_CHUNK 0x000003 /* use HTTP chunked transfer AND buffer packets */ + +#define SOAP_IO_LENGTH 0x000004 +#define SOAP_IO_KEEPALIVE 0x000008 + +#define SOAP_ENC_XML 0x000010 /* plain XML encoding, no HTTP header */ +#define SOAP_ENC_DIME 0x000020 +#define SOAP_ENC_ZLIB 0x000040 +#define SOAP_ENC_SSL 0x000080 + +#define SOAP_XML_STRICT 0x000100 /* input mode flag */ +#define SOAP_XML_CANONICAL 0x000200 /* output mode flag */ +#define SOAP_XML_TREE 0x000400 +#define SOAP_XML_GRAPH 0x000800 +#define SOAP_XML_NIL 0x001000 +#define SOAP_XML_DOM 0x002000 + +#define SOAP_C_NOIOB 0x010000 +#define SOAP_C_UTFSTRING 0x020000 +#define SOAP_C_MBSTRING 0x040000 +#define SOAP_C_LATIN 0x080000 + +#define SOAP_DOM_TREE 0x100000 +#define SOAP_DOM_NODE 0x200000 + +#define SOAP_IO_DEFAULT SOAP_IO_FLUSH + +/* SSL client/server authentication settings */ + +#define SOAP_SSL_NO_AUTHENTICATION 0x00 /* for testing purposes */ +#define SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION 0x01 /* client requires server to authenticate */ +#define SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION 0x02 /* server requires client to authenticate */ + +#define SOAP_SSL_DEFAULT SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION + +/* */ + +#define SOAP_BEGIN 0 +#define SOAP_IN_ENVELOPE 2 +#define SOAP_IN_HEADER 3 +#define SOAP_END_HEADER 4 +#define SOAP_IN_BODY 5 +#define SOAP_END_BODY 6 +#define SOAP_END_ENVELOPE 7 +#define SOAP_END 8 + +/* DEBUG macros */ + +#ifndef WITH_LEAN +# ifdef DEBUG +# ifndef SOAP_DEBUG +# define SOAP_DEBUG +# endif +# endif +#endif + +#ifdef SOAP_DEBUG +# ifndef SOAP_MESSAGE +# define SOAP_MESSAGE fprintf +# endif +# ifndef DBGLOG +# define DBGLOG(DBGFILE, CMD) \ +{ if (soap)\ + { if (!soap->fdebug[SOAP_INDEX_##DBGFILE])\ + soap_open_logfile(soap, SOAP_INDEX_##DBGFILE);\ + if (soap->fdebug[SOAP_INDEX_##DBGFILE])\ + { FILE *fdebug = soap->fdebug[SOAP_INDEX_##DBGFILE];\ + CMD;\ + fflush(fdebug);\ + }\ + }\ +} +# endif +# ifndef DBGMSG +# define DBGMSG(DBGFILE, MSG, LEN) \ +{ if (soap)\ + { if (!soap->fdebug[SOAP_INDEX_##DBGFILE])\ + soap_open_logfile(soap, SOAP_INDEX_##DBGFILE);\ + if (soap->fdebug[SOAP_INDEX_##DBGFILE])\ + { fwrite((MSG), 1, (LEN), soap->fdebug[SOAP_INDEX_##DBGFILE]);\ + fflush(soap->fdebug[SOAP_INDEX_##DBGFILE]);\ + }\ + }\ +} +# endif +#else +# define DBGLOG(DBGFILE, CMD) +# define DBGMSG(DBGFILE, MSG, LEN) +#endif + +typedef long wchar; /* 32 bit, for compatibility */ + +struct Namespace +{ const char *id; + const char *ns; + const char *in; + char *out; +}; + +struct soap_nlist +{ struct soap_nlist *next; + unsigned int level; + short index; /* corresponding entry in ns mapping table */ + char *ns; /* only set when parsed ns URI is not in the ns mapping table */ + char id[1]; /* the actual string value overflows into allocated region below this struct */ +}; + +struct soap_blist +{ struct soap_blist *next; + char *ptr; + size_t size; +}; + +struct soap_array +{ void *__ptr; + int __size; +}; + +/* pointer serialization management */ +struct soap_plist +{ struct soap_plist *next; + const void *ptr; + const struct soap_array *array; + int type; + int id; + char mark1; + char mark2; +}; + +/* class allocation list */ +struct soap_clist +{ struct soap_clist *next; + void *ptr; + int type; + int size; + void (*fdelete)(struct soap_clist*); +}; + +/* id-ref forwarding list */ +struct soap_ilist +{ struct soap_ilist *next; + int type; + size_t size; + void *link; + void *copy; + struct soap_flist *flist; + void *ptr; + unsigned int level; + char id[1]; /* the actual id string value overflows into allocated region below this struct */ +}; + +struct soap_attribute +{ struct soap_attribute *next; + short visible; + char *value; + size_t size; + char *ns; + char name[1]; /* the actual name string overflows into allocated region below this struct */ +}; + +struct soap_cookie +{ struct soap_cookie *next; + char *name; + char *value; + char *domain; + char *path; + long expire; /* client-side: local time to expire; server-side: seconds to expire */ + unsigned int version; + short secure; + short session; /* server-side */ + short env; /* server-side: got cookie from client */ + short modified; /* server-side: client cookie was modified */ +}; + +struct soap_dom_attribute +{ struct soap_dom_attribute *next; + const char *nstr; + char *name; + char *data; + wchar_t *wide; + struct soap *soap; +#ifdef __cplusplus + struct soap_dom_attribute &set(const char *nstr, const char *name); // set namespace and name + struct soap_dom_attribute &set(const char *data); // set data + void unlink(); + soap_dom_attribute(); + soap_dom_attribute(struct soap *soap); + soap_dom_attribute(struct soap *soap, const char *nstr, const char *name, const char *data); + ~soap_dom_attribute(); +#endif +}; + +#ifdef __cplusplus +class soap_dom_iterator +{ public: + struct soap_dom_element *elt; + const char *nstr; + const char *name; + int type; + bool operator==(const soap_dom_iterator&) const; + bool operator!=(const soap_dom_iterator&) const; + struct soap_dom_element &operator*() const; + soap_dom_iterator &operator++(); + soap_dom_iterator(); + soap_dom_iterator(struct soap_dom_element*); + ~soap_dom_iterator(); +}; +#endif + +struct soap_dom_element +{ struct soap_dom_element *next; /* next sibling */ + struct soap_dom_element *prnt; /* parent */ + struct soap_dom_element *elts; /* first child element */ + struct soap_dom_attribute *atts; /* first child attribute */ + const char *nstr; /* namespace string */ + char *name; /* element tag name */ + char *data; /* element content data (with SOAP_C_UTFSTRING flag set) */ + wchar_t *wide; /* element content data */ + int type; /* optional: serialized C/C++ data type */ + void *node; /* optional: pointer to serialized C/C++ data */ + struct soap *soap; +#ifdef __cplusplus + typedef soap_dom_iterator iterator; + struct soap_dom_element &set(const char *nstr, const char *name); + struct soap_dom_element &set(const char *data); + struct soap_dom_element &set(void *node, int type); + struct soap_dom_element &add(struct soap_dom_element*); + struct soap_dom_element &add(struct soap_dom_element&); + struct soap_dom_element &add(struct soap_dom_attribute*); + struct soap_dom_element &add(struct soap_dom_attribute&); + soap_dom_iterator begin(); + soap_dom_iterator end(); + soap_dom_iterator find(const char *nstr, const char *name); + soap_dom_iterator find(int type); + void unlink(); + soap_dom_element(); + soap_dom_element(struct soap *soap); + soap_dom_element(struct soap *soap, const char *nstr, const char *name); + soap_dom_element(struct soap *soap, const char *nstr, const char *name, const char *data); + soap_dom_element(struct soap *soap, const char *nstr, const char *name, void *node, int type); + ~soap_dom_element(); +#endif +}; + +#if defined(__cplusplus) && !defined(UNDER_CE) +} +extern ostream &operator<<(ostream&, const struct soap_dom_element&); +extern istream &operator>>(istream&, struct soap_dom_element&); +extern "C" { +#endif + +struct soap +{ short version; /* 1 = SOAP1.1 and 2 = SOAP1.2 (set automatically from namespace URI in nsmap table) */ + unsigned int mode; + unsigned int imode; + unsigned int omode; + short copy; /* 1 = copy of another soap struct */ + const char *float_format; /* points to user-definable format string for floats (<1024 chars) */ + const char *double_format; /* points to user-definable format string for doubles (<1024 chars) */ + const char *dime_id_format; /* points to user-definable format string for integer DIME id ( 0, gives socket recv timeout in seconds, < 0 in usec */ + int send_timeout; /* when > 0, gives socket send timeout in seconds, < 0 in usec */ + int connect_timeout; /* when > 0, gives socket connect() timeout in seconds, < 0 in usec */ + int accept_timeout; /* when > 0, gives socket accept() timeout in seconds, < 0 in usec */ + int socket_flags; /* socket recv() and send() flags, e.g. set to MSG_NOSIGNAL to disable sigpipe */ + int connect_flags; /* connect() SOL_SOCKET sockopt flags, e.g. set to SO_DEBUG to debug socket */ + int bind_flags; /* bind() SOL_SOCKET sockopt flags, e.g. set to SO_REUSEADDR to enable reuse */ + int accept_flags; /* accept() SOL_SOCKET sockopt flags */ + struct Namespace *namespaces; /* Pointer to global namespace mapping table */ + struct Namespace *local_namespaces; /* Local namespace mapping table */ + struct soap_nlist *nlist; /* namespace stack */ + struct soap_blist *blist; /* block allocation stack */ + struct soap_clist *clist; /* class instance allocation list */ + void *alist; /* memory allocation list */ + struct soap_ilist *iht[SOAP_IDHASH]; + struct soap_plist *pht[SOAP_PTRHASH]; + struct SOAP_ENV__Header *header; + struct SOAP_ENV__Fault *fault; + void *user; /* to pass user-defined data */ + struct soap_plugin *plugins; /* linked list of plug-in data */ + char *userid; /* HTTP Basic authorization userid */ + char *passwd; /* HTTP Basic authorization passwd */ + int (*fpost)(struct soap*, const char*, const char*, int, const char*, const char*, size_t); + int (*fget)(struct soap*); + int (*fposthdr)(struct soap*, const char*, const char*); + int (*fresponse)(struct soap*, int, size_t); + int (*fparse)(struct soap*); + int (*fparsehdr)(struct soap*, const char*, const char*); + int (*fconnect)(struct soap*, const char*, const char*, int); + int (*fdisconnect)(struct soap*); + int (*fopen)(struct soap*, const char*, const char*, int); + int (*faccept)(struct soap*, int, struct sockaddr*, int *n); + int (*fclose)(struct soap*); + int (*fsend)(struct soap*, const char*, size_t); + size_t (*frecv)(struct soap*, char*, size_t); + int (*fprepare)(struct soap*, const char*, size_t); + int (*fignore)(struct soap*, const char*); + void *(*fplugin)(struct soap*, const char*); + void *(*fdimereadopen)(struct soap*, void*, const char*, const char*, const char*); + void *(*fdimewriteopen)(struct soap*, const char*, const char*, const char*); + void (*fdimereadclose)(struct soap*, void*); + void (*fdimewriteclose)(struct soap*, void*); + size_t (*fdimeread)(struct soap*, void*, char*, size_t); + int (*fdimewrite)(struct soap*, void*, const char*, size_t); + int master; + int socket; +#if defined(__cplusplus) && !defined(UNDER_CE) + ostream *os; + istream *is; +#else + void *os; /* preserve alignment */ + void *is; /* preserve alignment */ +#endif +#ifndef UNDER_CE + int sendfd; + int recvfd; +#else + FILE *sendfd; + FILE *recvfd; + char errorstr[256]; + wchar_t werrorstr[256]; +#endif + size_t bufidx; + size_t buflen; + wchar ahead; + short cdata; + short body; + unsigned int level; + size_t count; /* message length counter */ + size_t length; /* message length as set by HTTP header */ + char *labbuf; /* look-aside buffer */ + size_t lablen; /* look-aside buffer allocated length */ + size_t labidx; /* look-aside buffer index to available part */ + char buf[SOAP_BUFLEN];/* send and receive buffer */ + char msgbuf[1024]; /* output buffer for (error) messages <=1024 bytes */ + char tmpbuf[1024]; /* output buffer for HTTP headers, simpleType values, attribute names, and DIME >=1024 bytes */ + char tag[SOAP_TAGLEN]; + char id[SOAP_TAGLEN]; + char href[SOAP_TAGLEN]; + char type[SOAP_TAGLEN]; + char arrayType[SOAP_TAGLEN]; + char arraySize[SOAP_TAGLEN]; + char arrayOffset[SOAP_TAGLEN]; + short other; + short root; + short position; + int positions[SOAP_MAXDIMS]; + struct soap_attribute *attributes; /* attribute list */ + short encoding; + short mustUnderstand; + short null; + short ns; + short part; + short alloced; + short peeked; + short dot_net_bug; + short keep_alive; + size_t chunksize; + size_t chunkbuflen; + char endpoint[SOAP_TAGLEN]; + char path[SOAP_TAGLEN]; + char host[SOAP_TAGLEN]; + char *action; + int port; + unsigned int max_keep_alive; + const char *proxy_host; /* Proxy Server host name */ + int proxy_port; /* Proxy Server port (default = 8080) */ + const char *proxy_userid; /* Proxy Authorization user name */ + const char *proxy_passwd; /* Proxy Authorization password */ + int status; /* -1 when request, else error code to be returned by server */ + int error; + int errmode; + int errnum; + unsigned long idnum; + unsigned long ip; + size_t dime_count; + int dime_flags; + size_t dime_size; + size_t dime_chunksize; + size_t dime_buflen; + char *dime_ptr; + char *dime_id; + char *dime_type; + char *dime_options; + struct soap_dom_element *dom; +#ifndef WITH_LEAN + const char *logfile[SOAP_MAXLOGS]; + FILE *fdebug[SOAP_MAXLOGS]; + struct soap_cookie *cookies; + const char *cookie_domain; + const char *cookie_path; + int cookie_max; +#endif +#ifdef WITH_OPENSSL + int (*fsslauth)(struct soap*); + int (*fsslverify)(int, X509_STORE_CTX*); + BIO *bio; + SSL *ssl; + SSL_CTX *ctx; + short require_server_auth; + short require_client_auth; + short rsa; /* when set, use RSA instead of DH */ + const char *keyfile; + const char *password; + const char *dhfile; + const char *cafile; + const char *capath; + const char *randfile; + SSL_SESSION *session; + char session_host[SOAP_TAGLEN]; + int session_port; +#endif +#ifdef WITH_ZLIB + short zlib_state; /* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_INFLATE */ + short zlib_in; /* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_GZIP */ + short zlib_out; /* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_GZIP */ + z_stream d_stream; /* decompression stream */ + char z_buf[SOAP_BUFLEN]; /* buffer */ + size_t z_buflen; + unsigned short z_level; /* compression level to be used (0=none, 1=fast to 9=best) */ + unsigned long z_crc; /* internal gzip crc */ + float z_ratio_in; /* detected compression ratio compressed_length/length of inbound message */ + float z_ratio_out; /* detected compression ratio compressed_length/length of outbound message */ +#endif +#ifdef PALM + UInt16 stdLibNum; + UInt16 stdLib2Num; + UInt16 stdLib3Num; + UInt16 genLibNum; + Err fH_errno; + Err fErrno; + Int32 timeout; + NetHostInfoBufType hostInfo; + UInt16 socketLibNum; +#endif +/* WR[ */ +#ifdef WMW_RPM_IO + void *rpmreqid; +#endif /* WMW_RPM_IO */ +/* ]WR */ +}; + +struct soap_code_map +{ long code; + const char *string; +}; + +/* forwarding list for container elements */ +struct soap_flist +{ struct soap_flist *next; + int type; + void *ptr; + unsigned int level; + void (*finsert)(struct soap*, int, void*, void*); +}; + +struct soap_plugin +{ struct soap_plugin *next; + const char *id; + void *data; + int (*fcopy)(struct soap *soap, struct soap_plugin *dst, struct soap_plugin *src); + void (*fdelete)(struct soap *soap, struct soap_plugin *p); /* should delete fields of plugin only and not free(p) */ +}; + +#ifndef WITH_NONAMESPACES +extern SOAP_NMAC struct Namespace namespaces[]; +#endif + +#ifdef HAVE_STRRCHR + #define soap_strrchr(s, t) strrchr(s, t) +#else + SOAP_FMAC1 char* SOAP_FMAC2 soap_strrchr(const char *s, int t); +#endif + +#ifdef HAVE_STRTOL + #define soap_strtol(s, t, b) strtol(s, t, b) +#else + SOAP_FMAC1 long SOAP_FMAC2 soap_strtol(const char *s, char **t, int b); +#endif + +#ifdef HAVE_STRTOUL + #define soap_strtoul(s, t, b) strtoul(s, t, b) +#else + SOAP_FMAC1 unsigned long SOAP_FMAC2 soap_strtoul(const char *s, char **t, int b); +#endif + +SOAP_FMAC1 void SOAP_FMAC2 soap_fault(struct soap*); +SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultcode(struct soap*); +SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultstring(struct soap*); +SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultdetail(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_serializeheader(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putheader(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getheader(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_serializefault(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putfault(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getfault(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_poll(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_connect_command(struct soap*, int, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_connect(struct soap*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_bind(struct soap*, const char*, int, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_accept(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_accept(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_server_context(struct soap*, unsigned short, const char*, const char*, const char*, const char*, const char*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_client_context(struct soap*, unsigned short, const char*, const char*, const char*, const char*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_puthttphdr(struct soap*, int status, size_t count); + +SOAP_FMAC1 int SOAP_FMAC2 soap_hash(const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_endpoint(struct soap*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_flush_raw(struct soap*, const char*, size_t); +SOAP_FMAC1 int SOAP_FMAC2 soap_flush(struct soap*); +SOAP_FMAC1 wchar SOAP_FMAC2 soap_get(struct soap*); +SOAP_FMAC1 wchar SOAP_FMAC2 soap_getchar(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_tag_cmp(const char*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_fault(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_sender_fault(struct soap*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_receiver_fault(struct soap*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_sender_error(struct soap*, const char*, const char*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_receiver_error(struct soap*, const char*, const char*, int); + +SOAP_FMAC1 int SOAP_FMAC2 soap_send_raw(struct soap*, const char*, size_t); +SOAP_FMAC1 int SOAP_FMAC2 soap_recv_raw(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_send(struct soap*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_recv(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_pututf8(struct soap*, unsigned long); +SOAP_FMAC1 wchar SOAP_FMAC2 soap_getutf8(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_putbase64(struct soap*, const unsigned char*, int); +SOAP_FMAC1 unsigned char* SOAP_FMAC2 soap_getbase64(struct soap*, int*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_puthex(struct soap*, const unsigned char*, int); +SOAP_FMAC1 unsigned char* SOAP_FMAC2 soap_gethex(struct soap*, int*); + + +SOAP_FMAC1 struct soap_ilist* SOAP_FMAC2 soap_lookup(struct soap*, const char*); +SOAP_FMAC1 struct soap_ilist* SOAP_FMAC2 soap_enter(struct soap*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_resolve_ptr(struct soap_ilist*); +SOAP_FMAC1 int SOAP_FMAC2 soap_resolve(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_lookup(struct soap*, const void *p, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_array_pointer_lookup(struct soap*, const void *p, const struct soap_array *a, int n, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_lookup_id(struct soap*, void *p, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_enter(struct soap*, const void *p, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_array_pointer_enter(struct soap*, const void *p, const struct soap_array *a, int t, struct soap_plist**); + +SOAP_FMAC1 int SOAP_FMAC2 soap_embed_element(struct soap *soap, const void *p, const char *tag, int type); +SOAP_FMAC1 int SOAP_FMAC2 soap_embed_array(struct soap *soap, const void *p, const struct soap_array *a, int n, const char *tag, int type); + +SOAP_FMAC1 void SOAP_FMAC2 soap_begin_count(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_begin_send(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_end_send(struct soap*); + +SOAP_FMAC1 void SOAP_FMAC2 soap_embedded(struct soap*, const void *p, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_reference(struct soap*, const void *p, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_array_reference(struct soap*, const void *p, const struct soap_array *a, int n, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_embedded_id(struct soap*, int id, const void *p, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_is_embedded(struct soap*, struct soap_plist*); +SOAP_FMAC1 int SOAP_FMAC2 soap_is_single(struct soap*, struct soap_plist*); +SOAP_FMAC1 int SOAP_FMAC2 soap_is_multi(struct soap*, struct soap_plist*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_embedded(struct soap*, struct soap_plist*); + +SOAP_FMAC1 const struct soap_code_map* SOAP_FMAC2 soap_code(const struct soap_code_map*, const char *str); +SOAP_FMAC1 long SOAP_FMAC2 soap_int_code(const struct soap_code_map*, const char *str, long other); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_str_code(const struct soap_code_map*, long code); + +SOAP_FMAC1 int SOAP_FMAC2 soap_getline(struct soap*, char*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_begin_recv(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_end_recv(struct soap*); + +SOAP_FMAC1 void* SOAP_FMAC2 soap_malloc(struct soap*, size_t); +SOAP_FMAC1 void SOAP_FMAC2 soap_dealloc(struct soap*, void*); +SOAP_FMAC1 struct soap_clist * SOAP_FMAC2 soap_link(struct soap*, void*, int, int, void (*fdelete)(struct soap_clist*)); +SOAP_FMAC1 void SOAP_FMAC2 soap_unlink(struct soap*, const void*); +SOAP_FMAC1 void SOAP_FMAC2 soap_free(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_lookup_type(struct soap*, const char *id); + +SOAP_FMAC1 void* SOAP_FMAC2 soap_id_lookup(struct soap*, const char *id, void **p, int t, size_t n, unsigned int k); +SOAP_FMAC1 void* SOAP_FMAC2 soap_id_forward(struct soap*, const char *id, void *p, int t, size_t n); +SOAP_FMAC1 void* SOAP_FMAC2 soap_id_enter(struct soap*, const char *id, void *p, int t, size_t n, int k); + +SOAP_FMAC1 int SOAP_FMAC2 soap_size(const int *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_getoffsets(const char *, const int *, int *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_getsize(const char *, const char *, int *); +SOAP_FMAC1 int SOAP_FMAC2 soap_getsizes(const char *, int *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_getposition(const char *, int *); + +SOAP_FMAC1 char* SOAP_FMAC2 soap_putsize(struct soap*, const char *, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_putsizesoffsets(struct soap*, const char *, const int *, const int *, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_putsizes(struct soap*, const char *, const int *, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_putoffset(struct soap*, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_putoffsets(struct soap*, const int *, int); + +SOAP_FMAC1 int SOAP_FMAC2 soap_closesock(struct soap*); + +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_new(void); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_new1(int); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_new2(int, int); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_copy(struct soap*); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_copy_context(struct soap*,struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_init(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_init1(struct soap*, int); +SOAP_FMAC1 void SOAP_FMAC2 soap_init2(struct soap*, int, int); +SOAP_FMAC1 void SOAP_FMAC2 soap_done(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_cleanup(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_begin(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_end(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_delete(struct soap*, void*); + +#ifndef WITH_LEAN +SOAP_FMAC1 void SOAP_FMAC2 soap_set_recv_logfile(struct soap*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_sent_logfile(struct soap*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_test_logfile(struct soap*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_close_logfiles(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_open_logfile(struct soap*, int); +#endif + +SOAP_FMAC1 char* SOAP_FMAC2 soap_value(struct soap*); + +SOAP_FMAC1 wchar SOAP_FMAC2 soap_advance(struct soap*); +SOAP_FMAC1 wchar SOAP_FMAC2 soap_skip(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_match_tag(struct soap*, const char*, const char *); +SOAP_FMAC1 int SOAP_FMAC2 soap_match_array(struct soap*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_element(struct soap*, const char*, int, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_begin_out(struct soap*, const char *tag, int id, const char *type); +SOAP_FMAC1 int SOAP_FMAC2 soap_array_begin_out(struct soap*, const char *tag, int id, const char *type, const char *offset); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_ref(struct soap*, const char *tag, int id, int href); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_href(struct soap*, const char *tag, int id, const char *href); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_null(struct soap*, const char *tag, int id, const char *type); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_result(struct soap*, const char *tag); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_end_out(struct soap*, const char *tag); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_start_end_out(struct soap*, const char *tag); + +SOAP_FMAC1 int SOAP_FMAC2 soap_attribute(struct soap*, const char*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_element_begin_in(struct soap*, const char *tag); + +SOAP_FMAC1 int SOAP_FMAC2 soap_element_end_in(struct soap*, const char *tag); + +SOAP_FMAC1 int SOAP_FMAC2 soap_peek_element(struct soap*); + +SOAP_FMAC1 void SOAP_FMAC2 soap_retry(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_revert(struct soap*); + +SOAP_FMAC1 char* SOAP_FMAC2 soap_strdup(struct soap*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_string_out(struct soap*, const char *s, int flag); +SOAP_FMAC1 char* SOAP_FMAC2 soap_string_in(struct soap*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_wstring_out(struct soap*, const wchar_t *s, int flag); +SOAP_FMAC1 wchar_t* SOAP_FMAC2 soap_wstring_in(struct soap*, int); + +SOAP_FMAC1 int SOAP_FMAC2 soap_match_namespace(struct soap*, const char *, const char*, int n1, int n2); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_default_namespace(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_set_namespaces(struct soap*, struct Namespace*); + +SOAP_FMAC1 void SOAP_FMAC2 soap_pop_namespace(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_push_namespace(struct soap*, const char *,const char *); +SOAP_FMAC1 int SOAP_FMAC2 soap_push_default_namespace(struct soap*, const char *, int); + +SOAP_FMAC1 int SOAP_FMAC2 soap_new_block(struct soap*); +SOAP_FMAC1 void* SOAP_FMAC2 soap_push_block(struct soap*, size_t); +SOAP_FMAC1 void SOAP_FMAC2 soap_pop_block(struct soap*); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_size_block(struct soap*, size_t); +SOAP_FMAC1 char* SOAP_FMAC2 soap_first_block(struct soap*); +SOAP_FMAC1 char* SOAP_FMAC2 soap_next_block(struct soap*); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_block_size(struct soap*); +SOAP_FMAC1 char* SOAP_FMAC2 soap_save_block(struct soap*, char*); +SOAP_FMAC1 char* SOAP_FMAC2 soap_store_block(struct soap*, char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_end_block(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_begin_out(struct soap*); +SOAP_FMAC1 int soap_envelope_end_out(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_begin_in(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_end_in(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_body_begin_out(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_body_end_out(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_body_begin_in(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_body_end_in(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_recv_header(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_response(struct soap*, int); + +SOAP_FMAC1 int SOAP_FMAC2 soap_send_fault(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_recv_fault(struct soap*); + +SOAP_FMAC1 void SOAP_FMAC2 soap_print_fault(struct soap*, FILE*); +SOAP_FMAC1 void SOAP_FMAC2 soap_print_fault_location(struct soap*, FILE*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_s2byte(struct soap*, const char*, char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2short(struct soap*, const char*, short*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2int(struct soap*, const char*, int*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2long(struct soap*, const char*, long*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2LONG64(struct soap*, const char*, LONG64*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2float(struct soap*, const char*, float*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2double(struct soap*, const char*, double*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedByte(struct soap*, const char*, unsigned char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedShort(struct soap*, const char*, unsigned short*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedInt(struct soap*, const char*, unsigned int*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedLong(struct soap*, const char*, unsigned long*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2ULONG64(struct soap*, const char*, ULONG64*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2dateTime(struct soap*, const char*, time_t*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2string(struct soap*, const char*, char**); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2QName(struct soap*, const char*, char**); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2base64(struct soap*, const unsigned char*, char*, size_t); + +SOAP_FMAC1 const char* SOAP_FMAC2 soap_byte2s(struct soap*, char); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_short2s(struct soap*, short); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_int2s(struct soap*, int); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_long2s(struct soap*, long); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_LONG642s(struct soap*, LONG64); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_float2s(struct soap*, float); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_double2s(struct soap*, double); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedByte2s(struct soap*, unsigned char); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedShort2s(struct soap*, unsigned short); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedInt2s(struct soap*, unsigned int); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedLong2s(struct soap*, unsigned long); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_ULONG642s(struct soap*, ULONG64); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_dateTime2s(struct soap*, time_t); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_QName2s(struct soap*, const char*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_base642s(struct soap*, const char*, char*, size_t, size_t*); + +SOAP_FMAC1 int* SOAP_FMAC2 soap_inint(struct soap*, const char *tag, int *p, const char *, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_inbyte(struct soap*, const char *tag, char *p, const char *, int); +SOAP_FMAC1 long* SOAP_FMAC2 soap_inlong(struct soap*, const char *tag, long *p, const char *, int); +SOAP_FMAC1 LONG64* SOAP_FMAC2 soap_inLONG64(struct soap*, const char *tag, LONG64 *p, const char *, int); +SOAP_FMAC1 short* SOAP_FMAC2 soap_inshort(struct soap*, const char *tag, short *p, const char *, int); +SOAP_FMAC1 float* SOAP_FMAC2 soap_infloat(struct soap*, const char *tag, float *p, const char *, int); +SOAP_FMAC1 double* SOAP_FMAC2 soap_indouble(struct soap*, const char *tag, double *p, const char *, int); +SOAP_FMAC1 unsigned char* SOAP_FMAC2 soap_inunsignedByte(struct soap*, const char *tag, unsigned char *p, const char *, int); +SOAP_FMAC1 unsigned short* SOAP_FMAC2 soap_inunsignedShort(struct soap*, const char *tag, unsigned short *p, const char *, int); +SOAP_FMAC1 unsigned int* SOAP_FMAC2 soap_inunsignedInt(struct soap*, const char *tag, unsigned int *p, const char *, int); +SOAP_FMAC1 unsigned long* SOAP_FMAC2 soap_inunsignedLong(struct soap*, const char *tag, unsigned long *p, const char *, int); +SOAP_FMAC1 ULONG64* SOAP_FMAC2 soap_inULONG64(struct soap*, const char *tag, ULONG64 *p, const char *, int); +SOAP_FMAC1 time_t* SOAP_FMAC2 soap_indateTime(struct soap*, const char *tag, time_t *p, const char *, int); +SOAP_FMAC1 char** SOAP_FMAC2 soap_instring(struct soap*, const char *tag, char **p, const char *, int, int); +SOAP_FMAC1 wchar_t** SOAP_FMAC2 soap_inwstring(struct soap*, const char *tag, wchar_t **p, const char *, int); +SOAP_FMAC1 char** SOAP_FMAC2 soap_inliteral(struct soap*, const char *tag, char **p); +SOAP_FMAC1 wchar_t** SOAP_FMAC2 soap_inwliteral(struct soap*, const char *tag, wchar_t **p); + +SOAP_FMAC1 int SOAP_FMAC2 soap_outbyte(struct soap*, const char *tag, int id, const char *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outshort(struct soap*, const char *tag, int id, const short *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outint(struct soap*, const char *tag, int id, const int *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outlong(struct soap*, const char *tag, int id, const long *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outLONG64(struct soap*, const char *tag, int id, const LONG64 *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outfloat(struct soap*, const char *tag, int id, const float *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outdouble(struct soap*, const char *tag, int id, const double *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedByte(struct soap*, const char *tag, int id, const unsigned char *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedShort(struct soap*, const char *tag, int id, const unsigned short *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedInt(struct soap*, const char *tag, int id, const unsigned int *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedLong(struct soap*, const char *tag, int id, const unsigned long *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outULONG64(struct soap*, const char *tag, int id, const ULONG64 *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outdateTime(struct soap*, const char *tag, int id, const time_t *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outstring(struct soap*, const char *tag, int id, char *const*p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outwstring(struct soap*, const char *tag, int id, wchar_t *const*p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outliteral(struct soap*, const char *tag, char *const*p); +SOAP_FMAC1 int SOAP_FMAC2 soap_outwliteral(struct soap*, const char *tag, wchar_t *const*p); + +#ifndef WITH_LEANER +SOAP_FMAC1 void SOAP_FMAC2 soap_set_attached(struct soap*, struct soap_plist*, const char*, const char*, const char*, size_t); +SOAP_FMAC1 int SOAP_FMAC2 soap_move(struct soap*, long); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_tell(struct soap*); +SOAP_FMAC1 char* SOAP_FMAC2 soap_dime_option(struct soap*, unsigned short, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getdimehdr(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getdime(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putdimehdr(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putdime(struct soap*, int, char*, char*, char*, void*, size_t); +#endif + +SOAP_FMAC1 int SOAP_FMAC2 soap_register_plugin_arg(struct soap*, int (*fcreate)(struct soap*, struct soap_plugin*, void*), void*); +SOAP_FMAC1 void* SOAP_FMAC2 soap_lookup_plugin(struct soap*, const char*); + +SOAP_FMAC1 struct soap_attribute * SOAP_FMAC2 soap_attr(struct soap *soap, const char *name); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_attr_value(struct soap *soap, const char *name); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_attr(struct soap *soap, const char *name, const char *value); +SOAP_FMAC1 void SOAP_FMAC2 soap_clr_attr(struct soap *soap); + +#ifdef WITH_COOKIES +SOAP_FMAC1 int SOAP_FMAC2 soap_encode_cookie(const char*, char*, int); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_decode_cookie(char*, int, const char*); +SOAP_FMAC1 extern struct soap_cookie* SOAP_FMAC2 soap_set_cookie(struct soap*, const char*, const char*, const char*, const char*); +SOAP_FMAC1 extern struct soap_cookie* SOAP_FMAC2 soap_cookie(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern char* SOAP_FMAC2 soap_cookie_value(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern long SOAP_FMAC2 soap_cookie_expire(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern int SOAP_FMAC2 soap_set_cookie_expire(struct soap*, const char*, long, const char*, const char*); +SOAP_FMAC1 extern int SOAP_FMAC2 soap_set_cookie_session(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern int SOAP_FMAC2 soap_clr_cookie_session(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern void SOAP_FMAC2 soap_clr_cookie(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern int SOAP_FMAC2 soap_getenv_cookies(struct soap*); +SOAP_FMAC1 extern struct soap_cookie* SOAP_FMAC2 soap_copy_cookies(struct soap*); +SOAP_FMAC1 extern void SOAP_FMAC2 soap_free_cookies(struct soap*); +#endif + +#if defined(PALM) && !defined(NOSHAREDLIB) && !(defined(BUILDING_STDSOAP) || defined(BUILDING_STDSOAP2) || defined(BUILDING_STDLIB) || defined(BUILDING_STDLIB2) || defined(PALM_1) || defined(PALM_2)) +# include "palmSharedLib.h" +#endif + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.0.c b/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.0.c new file mode 100644 index 0000000..fab9eee --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.0.c @@ -0,0 +1,11692 @@ +/* + +stdsoap2.c[pp] 2.7.0d + +Runtime environment. + +gSOAP XML Web services tools +Copyright (C) 2000-2004, Robert van Engelen, Genivia, Inc., All Rights Reserved. + +Contributors: + +Wind River Systems, Inc., for the following additions (marked WR[...]): + - vxWorks compatible + - Support for IPv6. + +-------------------------------------------------------------------------------- +gSOAP public license. + +The contents of this file are subject to the gSOAP Public License Version 1.3 +(the "License"); you may not use this file except in compliance with the +License. You may obtain a copy of the License at +http://www.cs.fsu.edu/~engelen/soaplicense.html +Software distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +for the specific language governing rights and limitations under the License. + +The Initial Developer of the Original Code is Robert A. van Engelen. +Copyright (C) 2000-2004, Robert van Engelen, Genivia, Inc., All Rights Reserved. +-------------------------------------------------------------------------------- +GPL license. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA + +Author contact information: +engelen@genivia.com / engelen@acm.org +-------------------------------------------------------------------------------- + +Installation note: + +Win32 build needs winsock.dll (Visual C++ "wsock32.lib") +To do this in Visual C++ 6.0, go to "Project", "settings", select the "Link" +tab (the project file needs to be selected in the file view) and add +"wsock32.lib" to the "Object/library modules" entry + +On Mac OS X with gcc (GCC) 3.1 20020420 (prerelease) you MUST compile with +-fstack_check when using -O2 because gcc 3.1 has a bug that smashes the stack +when locally allocated data exceeds 64K. + +*/ + +#include "stdsoap2.h" + +#ifdef __cplusplus +SOAP_SOURCE_STAMP("@(#) stdsoap2.cpp ver 2.7.0c 2004-09-27 12:00:00 GMT") +extern "C" { +#else +SOAP_SOURCE_STAMP("@(#) stdsoap2.c ver 2.7.0c 2004-09-27 12:00:00 GMT") +#endif + +/* 8bit character representing unknown/nonrepresentable character data (e.g. not supported by current locale) */ +#ifndef SOAP_UNKNOWN_CHAR +#define SOAP_UNKNOWN_CHAR (127) +#endif + +/* EOF=-1 */ +#define SOAP_LT (soap_wchar)(-2) /* XML character '<' */ +#define SOAP_TT (soap_wchar)(-3) /* XML character '' */ +#define SOAP_QT (soap_wchar)(-5) /* XML character '"' */ +#define SOAP_AP (soap_wchar)(-6) /* XML character ''' */ + +#define soap_blank(c) ((c) >= 0 && (c) <= 32) +#define soap_notblank(c) ((c) > 32) +#define soap_hash_ptr(p) (((unsigned long)(p) >> 3) & (SOAP_PTRHASH - 1)) + +static int soap_isxdigit(int); +static soap_wchar soap_char(struct soap*); +static soap_wchar soap_getchunkchar(struct soap*); +static void soap_update_ptrs(struct soap*, char*, char*, long); +static int soap_has_copies(struct soap*, const char*, const char*); +static struct soap_ilist *soap_hlookup(struct soap*, const char*); +static void soap_init_iht(struct soap*); +static void soap_free_iht(struct soap*); +static void soap_init_pht(struct soap*); +static void soap_free_pht(struct soap*); +static int soap_set_error(struct soap*, const char*, const char*, const char*, int); +static const char *soap_set_validation_fault(struct soap*, const char*, const char*); +static int soap_copy_fault(struct soap*, const char*, const char*, const char*); +static int soap_getattrval(struct soap*, char*, size_t, soap_wchar); +static void soap_set_local_namespaces(struct soap*); +static int soap_isnumeric(struct soap*, const char*); +static void *fplugin(struct soap*, const char*); +static const char *soap_decode(char*, size_t, const char*, const char*); + +#ifndef WITH_LEAN +static time_t soap_timegm(struct tm*); +#endif + +#ifdef SOAP_DEBUG +static void soap_init_logs(struct soap*); +static void soap_close_logfile(struct soap*, int); +static void soap_set_logfile(struct soap*, int, const char*); +#endif + +#ifdef WITH_FAST +static int soap_append_lab(struct soap*, const char*, size_t); +#endif + +#ifndef WITH_LEANER +static struct soap_multipart *soap_new_multipart(struct soap*, struct soap_multipart**, struct soap_multipart**, char*, size_t); +static int soap_putdimefield(struct soap*, const char*, size_t); +static char *soap_getdimefield(struct soap*, size_t); +static void soap_select_mime_boundary(struct soap*); +static int soap_valid_mime_boundary(struct soap*); +#endif + +#ifdef WITH_GZIP +static int soap_getgziphdr(struct soap*); +#endif + +#ifdef WITH_OPENSSL +static int ssl_auth_init(struct soap*); +static int ssl_verify_callback(int, X509_STORE_CTX*); +static int ssl_password(char*, int, int, void *); +static const char *ssl_error(struct soap*, int); +/* This callback is included for future references. It should not be deleted +static DH *ssl_tmp_dh(SSL*, int, int); +*/ +#endif + +static const char *soap_strerror(struct soap*); +static const char *tcp_error(struct soap*); +static const char *http_error(struct soap*, int); +static int http_post(struct soap*, const char*, const char*, int, const char*, const char*, size_t); +static int http_get(struct soap*); +static int http_send_header(struct soap*, const char*); +static int http_post_header(struct soap*, const char*, const char*); +static int http_response(struct soap*, int, size_t); +static int http_parse(struct soap*); +static int http_parse_header(struct soap*, const char*, const char*); +#ifndef MAC_CARBON +static int tcp_gethost(struct soap*, const char *addr, struct in_addr *inaddr); +static int tcp_connect(struct soap*, const char *endpoint, const char *host, int port); +static int tcp_accept(struct soap*, int, struct sockaddr*, int*); +static int tcp_disconnect(struct soap*); +static int tcp_closesocket(struct soap*, SOAP_SOCKET); +static int tcp_shutdownsocket(struct soap*, SOAP_SOCKET, int); +static int fsend(struct soap*, const char*, size_t); +static size_t frecv(struct soap*, char*, size_t); +#endif + +/* WR[ */ +#ifdef VXWORKS +static int vx_nonblocking = TRUE; /* ioctl argument */ +#endif +/* ]WR */ + +#if defined(PALM) && !defined(PALM_2) +unsigned short errno; +#endif + +#ifndef PALM_1 +static const char soap_env1[42] = "http://schemas.xmlsoap.org/soap/envelope/"; +static const char soap_enc1[42] = "http://schemas.xmlsoap.org/soap/encoding/"; +static const char soap_env2[40] = "http://www.w3.org/2003/05/soap-envelope"; +static const char soap_enc2[40] = "http://www.w3.org/2003/05/soap-encoding"; +static const char soap_rpc[35] = "http://www.w3.org/2003/05/soap-rpc"; +#endif + +#ifndef PALM_1 +const struct soap_double_nan soap_double_nan = {0xFFFFFFFF, 0xFFFFFFFF}; +static const char soap_base64o[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char soap_base64i[81] = "\76XXX\77\64\65\66\67\70\71\72\73\74\75XXXXXXX\00\01\02\03\04\05\06\07\10\11\12\13\14\15\16\17\20\21\22\23\24\25\26\27\30\31XXXXXX\32\33\34\35\36\37\40\41\42\43\44\45\46\47\50\51\52\53\54\55\56\57\60\61\62\63"; +#endif + +static const char soap_padding[3] = "\0\0"; +#define SOAP_STR_PADDING (soap_padding) +#define SOAP_STR_EOS (soap_padding) + +#ifndef WITH_LEAN +static const struct soap_code_map html_entity_codes[] = /* entities for XHTML parsing */ +{ { 160, "nbsp" }, + { 161, "iexcl" }, + { 162, "cent" }, + { 163, "pound" }, + { 164, "curren" }, + { 165, "yen" }, + { 166, "brvbar" }, + { 167, "sect" }, + { 168, "uml" }, + { 169, "copy" }, + { 170, "ordf" }, + { 171, "laquo" }, + { 172, "not" }, + { 173, "shy" }, + { 174, "reg" }, + { 175, "macr" }, + { 176, "deg" }, + { 177, "plusmn" }, + { 178, "sup2" }, + { 179, "sup3" }, + { 180, "acute" }, + { 181, "micro" }, + { 182, "para" }, + { 183, "middot" }, + { 184, "cedil" }, + { 185, "sup1" }, + { 186, "ordm" }, + { 187, "raquo" }, + { 188, "frac14" }, + { 189, "frac12" }, + { 190, "frac34" }, + { 191, "iquest" }, + { 192, "Agrave" }, + { 193, "Aacute" }, + { 194, "Acirc" }, + { 195, "Atilde" }, + { 196, "Auml" }, + { 197, "Aring" }, + { 198, "AElig" }, + { 199, "Ccedil" }, + { 200, "Egrave" }, + { 201, "Eacute" }, + { 202, "Ecirc" }, + { 203, "Euml" }, + { 204, "Igrave" }, + { 205, "Iacute" }, + { 206, "Icirc" }, + { 207, "Iuml" }, + { 208, "ETH" }, + { 209, "Ntilde" }, + { 210, "Ograve" }, + { 211, "Oacute" }, + { 212, "Ocirc" }, + { 213, "Otilde" }, + { 214, "Ouml" }, + { 215, "times" }, + { 216, "Oslash" }, + { 217, "Ugrave" }, + { 218, "Uacute" }, + { 219, "Ucirc" }, + { 220, "Uuml" }, + { 221, "Yacute" }, + { 222, "THORN" }, + { 223, "szlig" }, + { 224, "agrave" }, + { 225, "aacute" }, + { 226, "acirc" }, + { 227, "atilde" }, + { 228, "auml" }, + { 229, "aring" }, + { 230, "aelig" }, + { 231, "ccedil" }, + { 232, "egrave" }, + { 233, "eacute" }, + { 234, "ecirc" }, + { 235, "euml" }, + { 236, "igrave" }, + { 237, "iacute" }, + { 238, "icirc" }, + { 239, "iuml" }, + { 240, "eth" }, + { 241, "ntilde" }, + { 242, "ograve" }, + { 243, "oacute" }, + { 244, "ocirc" }, + { 245, "otilde" }, + { 246, "ouml" }, + { 247, "divide" }, + { 248, "oslash" }, + { 249, "ugrave" }, + { 250, "uacute" }, + { 251, "ucirc" }, + { 252, "uuml" }, + { 253, "yacute" }, + { 254, "thorn" }, + { 255, "yuml" }, + { 0, NULL } +}; +#endif + +#ifndef WITH_LEAN +static const struct soap_code_map h_error_codes[] = +{ +#ifdef HOST_NOT_FOUND + { HOST_NOT_FOUND, "Host not found" }, +#endif +#ifdef TRY_AGAIN + { TRY_AGAIN, "Try Again" }, +#endif +#ifdef NO_RECOVERY + { NO_RECOVERY, "No Recovery" }, +#endif +#ifdef NO_DATA + { NO_DATA, "No Data" }, +#endif +#ifdef NO_ADDRESS + { NO_ADDRESS, "No Address" }, +#endif + { 0, NULL } +}; +#endif + +#ifndef WITH_LEAN +static const struct soap_code_map h_http_error_codes[] = +{ { 201, "Created" }, + { 202, "Accepted" }, + { 203, "Non-Authoritative Information" }, + { 204, "No Content" }, + { 205, "Reset Content" }, + { 206, "Partial Content" }, + { 300, "Multiple Choices" }, + { 301, "Moved Permanently" }, + { 302, "Found" }, + { 303, "See Other" }, + { 304, "Not Modified" }, + { 305, "Use Proxy" }, + { 307, "Temporary Redirect" }, + { 400, "Bad Request" }, + { 401, "Unauthorized" }, + { 402, "Payment Required" }, + { 403, "Forbidden" }, + { 404, "Not Found" }, + { 405, "Method Not Allowed" }, + { 406, "Not Acceptable" }, + { 407, "Proxy Authentication Required" }, + { 408, "Request Time-out" }, + { 409, "Conflict" }, + { 410, "Gone" }, + { 411, "Length Required" }, + { 412, "Precondition Failed" }, + { 413, "Request Entity Too Large" }, + { 414, "Request-URI Too Large" }, + { 415, "Unsupported Media Type" }, + { 416, "Requested range not satisfiable" }, + { 417, "Expectation Failed" }, + { 500, "Internal Server Error" }, + { 501, "Not Implemented" }, + { 502, "Bad Gateway" }, + { 503, "Service Unavailable" }, + { 504, "Gateway Time-out" }, + { 505, "HTTP Version not supported" }, + { 0, NULL } +}; +#endif + +#ifdef WITH_OPENSSL +static const struct soap_code_map h_ssl_error_codes[] = +{ +#define _SSL_ERROR(e) { e, #e } + _SSL_ERROR(SSL_ERROR_SSL), + _SSL_ERROR(SSL_ERROR_ZERO_RETURN), + _SSL_ERROR(SSL_ERROR_WANT_READ), + _SSL_ERROR(SSL_ERROR_WANT_WRITE), + _SSL_ERROR(SSL_ERROR_WANT_CONNECT), + _SSL_ERROR(SSL_ERROR_WANT_X509_LOOKUP), + _SSL_ERROR(SSL_ERROR_SYSCALL), + { 0, NULL } +}; +#endif + +#ifndef WITH_LEANER +static const struct soap_code_map mime_codes[] = +{ { SOAP_MIME_7BIT, "7bit" }, + { SOAP_MIME_8BIT, "8bit" }, + { SOAP_MIME_BINARY, "binary" }, + { SOAP_MIME_QUOTED_PRINTABLE, "quoted-printable" }, + { SOAP_MIME_BASE64, "base64" }, + { SOAP_MIME_IETF_TOKEN, "ietf-token" }, + { SOAP_MIME_X_TOKEN, "x-token" }, + { 0, NULL } +}; +#endif + +#ifdef WIN32 +static int tcp_done = 0; +#endif + +/******************************************************************************/ +#ifndef MAC_CARBON +#ifndef PALM_1 +static int +fsend(struct soap *soap, const char *s, size_t n) +{ register int nwritten; +#if defined(__cplusplus) && !defined(WITH_LEAN) + if (soap->os) + { soap->os->write(s, n); + if (soap->os->good()) + return SOAP_OK; + return SOAP_EOF; + } +#endif + while (n) + { if (soap_valid_socket(soap->socket)) + { +#ifndef WITH_LEAN + if (soap->send_timeout) + { struct timeval timeout; + fd_set fd; + if (soap->send_timeout > 0) + { timeout.tv_sec = soap->send_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->send_timeout/1000000; + timeout.tv_usec = -soap->send_timeout%1000000; + } + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->socket, &fd); + for (;;) + { register int r = select((SOAP_SOCKET)(soap->socket + 1), NULL, &fd, &fd, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + return SOAP_EOF; + } + if (soap_socket_errno != SOAP_EINTR) + { soap->errnum = soap_socket_errno; + return SOAP_EOF; + } + } + } +#endif +#ifdef WITH_OPENSSL + if (soap->ssl) + nwritten = SSL_write(soap->ssl, s, n); + else +#endif +#ifndef PALM + nwritten = send((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags); +#else + nwritten = send((SOAP_SOCKET)soap->socket, (void*)s, n, soap->socket_flags); +#endif + if (nwritten <= 0) + { +#ifdef WITH_OPENSSL + int err; + if (soap->ssl && (err = SSL_get_error(soap->ssl, nwritten)) != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) + return SOAP_EOF; +#endif + if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EWOULDBLOCK && soap_socket_errno != SOAP_EAGAIN) + { soap->errnum = soap_socket_errno; + return SOAP_EOF; + } + nwritten = 0; /* and call write() again */ + } + } + else + { +#ifdef WITH_FASTCGI + nwritten = fwrite((void*)s, 1, n, stdout); + fflush(stdout); +#else +#ifdef UNDER_CE + nwritten = fwrite(s, 1, n, soap->sendfd); +#else +/* WR[ */ +#ifdef VXWORKS +#ifdef WMW_RPM_IO + if (soap->rpmreqid) + { + httpBlockPut(soap->rpmreqid, s, n); + nwritten = n; + } + else + { + nwritten = fwrite(s, sizeof(char), n, fdopen(soap->sendfd, "w")); + } +#else + nwritten = fwrite(s, sizeof(char), n, fdopen(soap->sendfd, "w")); +#endif /* WMW_RPM_IO */ +#else +/* ]WR */ + nwritten = write((SOAP_SOCKET)soap->sendfd, s, n); +/* WR[ */ +#endif +/* ]WR */ +#endif +#endif + if (nwritten <= 0) + { if (soap_errno != SOAP_EINTR && soap_errno != SOAP_EWOULDBLOCK && soap_errno != SOAP_EAGAIN) + { soap->errnum = soap_errno; + return SOAP_EOF; + } + nwritten = 0; /* and call write() again */ + } + } + n -= nwritten; + s += nwritten; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_flush_raw(struct soap *soap, const char *s, size_t n) +{ if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) + { register char *t; + if (!(t = (char*)soap_push_block(soap, n))) + return soap->error = SOAP_EOM; + memcpy(t, s, n); + if (soap->fpreparesend) + return soap->fpreparesend(soap, s, n); + return SOAP_OK; + } + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) + { char t[16]; + sprintf(t, "\r\n%lX\r\n" + (soap->chunksize ? 0 : 2), (unsigned long)n); + DBGMSG(SENT, t, strlen(t)); + if ((soap->error = soap->fsend(soap, t, strlen(t)))) + return soap->error; + soap->chunksize += n; + } + DBGMSG(SENT, s, n); + return soap->error = soap->fsend(soap, s, n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_flush(struct soap *soap) +{ if (soap->bufidx) + { +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { soap->d_stream.next_in = (Byte*)soap->buf; + soap->d_stream.avail_in = (unsigned int)soap->bufidx; +#ifdef WITH_GZIP + soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->bufidx); +#endif + do + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating %u bytes\n", soap->d_stream.avail_in)); + if (deflate(&soap->d_stream, Z_NO_FLUSH) != Z_OK) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to deflate: %s\n", soap->d_stream.msg?soap->d_stream.msg:"")); + return soap->error = SOAP_ZLIB_ERROR; + } + if (!soap->d_stream.avail_out) + { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN)) + return soap->error; + soap->d_stream.next_out = (Byte*)soap->z_buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + } + } while (soap->d_stream.avail_in); + } + else +#endif + if (soap_flush_raw(soap, soap->buf, soap->bufidx)) + return soap->error; + soap->bufidx = 0; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send_raw(struct soap *soap, const char *s, size_t n) +{ if (!n) + return SOAP_OK; + if (soap->mode & SOAP_IO_LENGTH) + { soap->count += n; + if (soap->fpreparesend && (soap->mode & SOAP_IO) != SOAP_IO_STORE) + return soap->fpreparesend(soap, s, n); + return SOAP_OK; + } + if (soap->mode & SOAP_IO) + { register size_t i = SOAP_BUFLEN - soap->bufidx; + while (n >= i) + { memcpy(soap->buf + soap->bufidx, s, i); + soap->bufidx = SOAP_BUFLEN; + if (soap_flush(soap)) + return soap->error; + s += i; + n -= i; + i = SOAP_BUFLEN; + } + memcpy(soap->buf + soap->bufidx, s, n); + soap->bufidx += n; + return SOAP_OK; + } + return soap_flush_raw(soap, s, n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send(struct soap *soap, const char *s) +{ if (s) + return soap_send_raw(soap, s, strlen(s)); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send2(struct soap *soap, const char *s1, const char *s2) +{ if (soap_send(soap, s1)) + return soap->error; + return soap_send(soap, s2); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send3(struct soap *soap, const char *s1, const char *s2, const char *s3) +{ if (soap_send(soap, s1) + || soap_send(soap, s2)) + return soap->error; + return soap_send(soap, s3); +} +#endif + +/******************************************************************************/ +#ifndef MAC_CARBON +#ifndef PALM_1 +static size_t +frecv(struct soap *soap, char *s, size_t n) +{ register int r; + soap->errnum = 0; +#if defined(__cplusplus) && !defined(WITH_LEAN) + if (soap->is) + { if (soap->is->good()) + return soap->is->read(s, n).gcount(); + return 0; + } +#endif + if (soap_valid_socket(soap->socket)) + { for (;;) + { +#ifndef WITH_LEAN + struct timeval timeout; + fd_set fd; + if (soap->recv_timeout) + { if (soap->recv_timeout > 0) + { timeout.tv_sec = soap->recv_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->recv_timeout/1000000; + timeout.tv_usec = -soap->recv_timeout%1000000; + } + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->socket, &fd); + for (;;) + { r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout); + if (r > 0) + break; + if (r == 0) + return 0; + if (soap_socket_errno != SOAP_EINTR) + { soap->errnum = soap_socket_errno; + return 0; + } + } + } +#endif +#ifdef WITH_OPENSSL + if (soap->ssl) + { int err; + r = SSL_read(soap->ssl, s, n); + if ((err = SSL_get_error(soap->ssl, r)) == SSL_ERROR_NONE) + return (size_t)r; + if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) + return 0; + } + else +#endif + { r = recv((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags); + if (r >= 0) + return (size_t)r; + if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EAGAIN) + { soap->errnum = soap_socket_errno; + return 0; + } + } +#ifndef WITH_LEAN + { struct timeval timeout; + fd_set fd; + timeout.tv_sec = 0; + timeout.tv_usec = 10000; + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->socket, &fd); + r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout); + if (r < 0 && soap_socket_errno != SOAP_EINTR) + { soap->errnum = soap_socket_errno; + return 0; + } + } +#endif + } + } +#ifdef WITH_FASTCGI + return fread(s, 1, n, stdin); +#else +#ifdef UNDER_CE + return fread(s, 1, n, soap->recvfd); +#else +/* WR[ */ +#ifdef WMW_RPM_IO + if (soap->rpmreqid) + r = httpBlockRead(soap->rpmreqid, s, n); + else + r = read(soap->recvfd, s, n); + if (r >= 0) + return r; + return 0; +#else +/* ]WR */ + r = read((SOAP_SOCKET)soap->recvfd, s, n); + if (r >= 0) + return (size_t)r; + soap->errnum = soap_errno; + return 0; +/* WR[ */ +#endif +/* ]WR */ +#endif +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static soap_wchar +soap_getchunkchar(struct soap *soap) +{ if (soap->bufidx < soap->buflen) + return soap->buf[soap->bufidx++]; + soap->bufidx = 0; + soap->buflen = soap->chunkbuflen = soap->frecv(soap, soap->buf, SOAP_BUFLEN); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes\n", (unsigned int)soap->buflen)); + DBGMSG(RECV, soap->buf, soap->buflen); + if (soap->buflen) + return soap->buf[soap->bufidx++]; + return EOF; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +soap_isxdigit(int c) +{ switch (c) + { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + return 1; + } + return 0; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv_raw(struct soap *soap) +{ register size_t ret; +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { if (soap->d_stream.next_out == Z_NULL) + return EOF; + if (soap->d_stream.avail_in || !soap->d_stream.avail_out) + { register int r; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflating\n")); + soap->d_stream.next_out = (Byte*)soap->buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + r = inflate(&soap->d_stream, Z_NO_FLUSH); + if (r == Z_OK || r == Z_STREAM_END) + { soap->bufidx = 0; + soap->buflen = SOAP_BUFLEN - soap->d_stream.avail_out; + if (soap->zlib_in == SOAP_ZLIB_GZIP) + soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen); + if (r == Z_STREAM_END) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out)); + soap->z_ratio_in = (float)soap->d_stream.total_in / (float)soap->d_stream.total_out; + soap->d_stream.next_out = Z_NULL; + } + if (soap->buflen) + { soap->count += soap->buflen; + return SOAP_OK; + } + } + else if (r != Z_BUF_ERROR) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate error: %s\n", soap->d_stream.msg?soap->d_stream.msg:"")); + soap->d_stream.next_out = Z_NULL; + return EOF; + } + } +zlib_again: + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK && !soap->chunksize) + { memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN); + soap->buflen = soap->z_buflen; + } + } +#endif + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) /* read HTTP chunked transfer */ + { +chunk_again: + if (soap->chunksize) + { soap->buflen = ret = soap->frecv(soap, soap->buf, soap->chunksize > SOAP_BUFLEN ? SOAP_BUFLEN : soap->chunksize); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk: read %u bytes\n", (unsigned int)ret)); + DBGMSG(RECV, soap->buf, ret); + soap->bufidx = 0; + soap->chunksize -= ret; + } + else + { register soap_wchar c; + char *t, tmp[8]; + t = tmp; + if (!soap->chunkbuflen) + { soap->chunkbuflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes\n", (unsigned int)ret)); + DBGMSG(RECV, soap->buf, ret); + soap->bufidx = 0; + if (!ret) + return EOF; + } + else + soap->bufidx = soap->buflen; + soap->buflen = soap->chunkbuflen; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk size (%u %u)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen)); + while (!soap_isxdigit((int)(c = soap_getchunkchar(soap)))) + if ((int)c == EOF) + return EOF; + do + *t++ = (char)c; + while (soap_isxdigit((int)(c = soap_getchunkchar(soap))) && t - tmp < 7); + while ((int)c != EOF && c != '\n') + c = soap_getchunkchar(soap); + if ((int)c == EOF) + return EOF; + *t = '\0'; + soap->chunksize = soap_strtoul(tmp, &t, 16); + if (!soap->chunksize) + { soap->chunkbuflen = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of chunked message\n")); + while ((int)c != EOF && c != '\n') + c = soap_getchunkchar(soap); + return EOF; + } + soap->buflen = soap->bufidx + soap->chunksize; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving buf len to %u (%u %s)\n", (unsigned int)soap->buflen, (unsigned int)soap->bufidx, tmp)); + if (soap->buflen > soap->chunkbuflen) + { soap->buflen = soap->chunkbuflen; + soap->chunksize -= soap->buflen - soap->bufidx; + soap->chunkbuflen = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Passed end of buffer for chunked HTTP (%lu bytes left)\n", (unsigned long)(soap->buflen - soap->bufidx))); + } + else if (soap->chunkbuflen) + soap->chunksize = 0; + ret = soap->buflen - soap->bufidx; + if (!ret) + goto chunk_again; + } + } + else + { soap->bufidx = 0; + soap->buflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes\n", (unsigned int)ret)); + DBGMSG(RECV, soap->buf, ret); + } + if (soap->fpreparerecv && (soap->error = soap->fpreparerecv(soap, soap->buf, ret))) + return soap->error; +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { register int r; + memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); + soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx); + soap->d_stream.avail_in = (unsigned int)ret; + soap->d_stream.next_out = (Byte*)soap->buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + r = inflate(&soap->d_stream, Z_NO_FLUSH); + if (r == Z_OK || r == Z_STREAM_END) + { soap->bufidx = 0; + soap->z_buflen = soap->buflen; + soap->buflen = ret = SOAP_BUFLEN - soap->d_stream.avail_out; + if (soap->zlib_in == SOAP_ZLIB_GZIP) + soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %u bytes\n", (unsigned int)ret)); + if (!ret) + goto zlib_again; + if (r == Z_STREAM_END) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out)); + soap->z_ratio_in = (float)soap->d_stream.total_in / (float)soap->d_stream.total_out; + soap->d_stream.next_out = Z_NULL; + } + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to inflate: (%d) %s\n", r, soap->d_stream.msg?soap->d_stream.msg:"")); + soap->d_stream.next_out = Z_NULL; + return EOF; + } + } +#endif + soap->count += ret; + return !ret; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv(struct soap *soap) +{ +#ifndef WITH_LEANER + if (soap->mode & SOAP_ENC_DIME) + { if (soap->dime.buflen) + { char *s; + int i; + unsigned char tmp[12]; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME hdr for chunked DIME is in buffer\n")); + soap->count += soap->dime.buflen - soap->buflen; + soap->buflen = soap->dime.buflen; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Skip padding (%ld bytes)\n", -(long)soap->dime.size&3)); + for (i = -(long)soap->dime.size&3; i > 0; i--) + { soap->bufidx++; + if (soap->bufidx >= soap->buflen) + if (soap_recv_raw(soap)) + return EOF; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME hdr for next chunk\n")); + s = (char*)tmp; + for (i = 12; i > 0; i--) + { *s++ = soap->buf[soap->bufidx++]; + if (soap->bufidx >= soap->buflen) + if (soap_recv_raw(soap)) + return EOF; + } + soap->dime.flags = tmp[0] & 0x7; + soap->dime.size = ((size_t)tmp[8] << 24) | ((size_t)tmp[9] << 16) | ((size_t)tmp[10] << 8) | ((size_t)tmp[11]); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME chunk (%u bytes)\n", (unsigned int)soap->dime.size)); + if (soap->dime.flags & SOAP_DIME_CF) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "More chunking\n")); + soap->dime.chunksize = soap->dime.size; + if (soap->buflen - soap->bufidx >= soap->dime.size) + { soap->dime.buflen = soap->buflen; + soap->buflen = soap->bufidx + soap->dime.chunksize; + } + else + soap->dime.chunksize -= soap->buflen - soap->bufidx; + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Last chunk\n")); + soap->dime.buflen = 0; + soap->dime.chunksize = 0; + } + soap->count = soap->buflen - soap->bufidx; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%u bytes remaining\n", (unsigned int)soap->count)); + return SOAP_OK; + } + if (soap->dime.chunksize) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get next DIME hdr for chunked DIME (%u bytes chunk)\n", (unsigned int)soap->dime.chunksize)); + if (soap_recv_raw(soap)) + return EOF; + if (soap->buflen - soap->bufidx >= soap->dime.chunksize) + { soap->dime.buflen = soap->buflen; + soap->count -= soap->buflen - soap->bufidx - soap->dime.chunksize; + soap->buflen = soap->bufidx + soap->dime.chunksize; + } + else + soap->dime.chunksize -= soap->buflen - soap->bufidx; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%lu bytes remaining, count=%u\n", (unsigned long)(soap->buflen-soap->bufidx), (unsigned int)soap->count)); + return SOAP_OK; + } + } +#endif + return soap_recv_raw(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +soap_wchar +SOAP_FMAC2 +soap_getchar(struct soap *soap) +{ register soap_wchar c; + if (soap->ahead) + { c = soap->ahead; + soap->ahead = 0; + return c; + } + return soap_get1(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +const struct soap_code_map* +SOAP_FMAC2 +soap_code(const struct soap_code_map *map, const char *str) +{ while (map->string) + { if (!strcmp(str, map->string)) /* case sensitive */ + return map; + map++; + } + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +long +SOAP_FMAC2 +soap_int_code(const struct soap_code_map *map, const char *str, long other) +{ while (map->string) + { if (!soap_tag_cmp(str, map->string)) /* case insensitive */ + return map->code; + map++; + } + return other; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_str_code(const struct soap_code_map *map, long code) +{ while (map->code != code && map->string) + map++; + return map->string; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static soap_wchar +soap_char(struct soap *soap) +{ char tmp[8]; + register int i; + register soap_wchar c; + register char *s = tmp; + for (i = 0; i < 7; i++) + { c = soap_get1(soap); + if (c == ';' || (int)c == EOF) + break; + *s++ = (char)c; + } + *s = '\0'; + if (*tmp == '#') + { if (tmp[1] == 'x' || tmp[1] == 'X') + return soap_strtol(tmp + 2, NULL, 16); + return atol(tmp + 1); + } + if (!strcmp(tmp, "lt")) + return '<'; + if (!strcmp(tmp, "gt")) + return '>'; + if (!strcmp(tmp, "amp")) + return '&'; + if (!strcmp(tmp, "quot")) + return '"'; + if (!strcmp(tmp, "apos")) + return '\''; +#ifndef WITH_LEAN + return (soap_wchar)soap_int_code(html_entity_codes, tmp, SOAP_UNKNOWN_CHAR); +#else + return SOAP_UNKNOWN_CHAR; /* use this to represent unknown code */ +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +soap_wchar +SOAP_FMAC2 +soap_get(struct soap *soap) +{ register soap_wchar c; + c = soap->ahead; + if (c) + soap->ahead = 0; + else + c = soap_get1(soap); + for (;;) + { if (soap->cdata) + { if (c == ']') + { c = soap_get1(soap); + if (c == ']') + { soap->cdata = 0; + soap_get1(soap); /* skip > */ + c = soap_get1(soap); + } + else + { soap_revget1(soap); + return ']'; + } + } + else + return c; + } + switch (c) + { case '<': + do c = soap_get1(soap); + while (soap_blank(c)); + if (c == '!' || c == '?' || c == '%') + { if (c == '!') + { c = soap_get1(soap); + if (c == '[') + { do c = soap_get1(soap); + while ((int)c != EOF && c != '['); + if ((int)c == EOF) + break; + soap->cdata = 1; + c = soap_get1(soap); + continue; + } + if (c == '-' && (c = soap_get1(soap)) == '-') + { do + { c = soap_get1(soap); + if (c == '-' && (c = soap_get1(soap)) == '-') + break; + } while ((int)c != EOF); + } + } + while ((int)c != EOF && c != '>') + c = soap_get1(soap); + if ((int)c == EOF) + break; + c = soap_get1(soap); + continue; + } + if (c == '/') + return SOAP_TT; + soap_revget1(soap); + return SOAP_LT; + case '>': + return SOAP_GT; + case '"': + return SOAP_QT; + case '\'': + return SOAP_AP; + case '&': + return soap_char(soap) | 0x80000000; + } + break; + } + return c; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +soap_wchar +SOAP_FMAC2 +soap_advance(struct soap *soap) +{ register soap_wchar c; + while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT) + ; + return c; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +soap_wchar +SOAP_FMAC2 +soap_skip(struct soap *soap) +{ register soap_wchar c; + do c = soap_get(soap); + while (soap_blank(c)); + return c; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_move(struct soap *soap, long n) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving %ld bytes forward\n", (long)n)); + for (; n > 0; n--) + if ((int)soap_getchar(soap) == EOF) + return SOAP_EOF; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_tell(struct soap *soap) +{ return soap->count - soap->buflen + soap->bufidx - (soap->ahead != 0); +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_pututf8(struct soap *soap, register unsigned long c) +{ char tmp[16]; + if (c > 0 && c < 0x80) + { *tmp = (char)c; + return soap_send_raw(soap, tmp, 1); + } +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { register char *t = tmp; + if (c < 0x0800) + *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); + else + { if (c < 0x010000) + *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + else + { if (c < 0x200000) + *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + else + { if (c < 0x04000000) + *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + else + { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + } + *t++ = (char)(0x80 | (c & 0x3F)); + *t = '\0'; + } + else +#endif + sprintf(tmp, "&#%lu;", c); + return soap_send(soap, tmp); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +soap_wchar +SOAP_FMAC2 +soap_getutf8(struct soap *soap) +{ register soap_wchar c, c1, c2, c3, c4; + c = soap_get(soap); + if (c < 0x80 || (soap->mode & SOAP_ENC_LATIN)) + return c; + c1 = soap_get(soap); + if (c1 < 0x80) + { soap_unget(soap, c1); + return c; + } + c1 &= 0x3F; + if (c < 0xE0) + return ((soap_wchar)(c & 0x1F) << 6) | c1; + c2 = (soap_wchar)soap_get1(soap) & 0x3F; + if (c < 0xF0) + return ((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2; + c3 = (soap_wchar)soap_get1(soap) & 0x3F; + if (c < 0xF8) + return ((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3; + c4 = (soap_wchar)soap_get1(soap) & 0x3F; + if (c < 0xFC) + return ((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4; + return ((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(soap_get1(soap) & 0x3F); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_puthex(struct soap *soap, const unsigned char *s, int n) +{ /* TODO: serialize to DOM (as an option) using new soap_s2hex() */ + char d[2]; + register int i; + for (i = 0; i < n; i++) + { register int m = *s++; + d[0] = (char)((m >> 4) + (m > 159 ? '7' : '0')); + m &= 0x0F; + d[1] = (char)(m + (m > 9 ? '7' : '0')); + if (soap_send_raw(soap, d, 2)) + return soap->error; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +unsigned char* +SOAP_FMAC2 +soap_gethex(struct soap *soap, int *n) +{ +#ifdef WITH_FAST + soap->labidx = 0; + for (;;) + { register char *s; + register int i, k; + if (soap_append_lab(soap, NULL, 0)) + return NULL; + s = soap->labbuf + soap->labidx; + k = soap->lablen - soap->labidx; + soap->labidx = soap->lablen; + for (i = 0; i < k; i++) + { register char d1, d2; + register soap_wchar c; + c = soap_get(soap); + if (soap_isxdigit(c)) + { d1 = (char)c; + c = soap_get(soap); + if (soap_isxdigit(c)) + d2 = (char)c; + else + { soap->error = SOAP_TYPE; + return NULL; + } + } + else + { unsigned char *p; + soap_unget(soap, c); + if (n) + *n = (int)(soap->lablen - k + i); + p = (unsigned char*)soap_malloc(soap, soap->lablen - k + i); + if (p) + memcpy(p, soap->labbuf, soap->lablen - k + i); + return p; + } + *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'); + } + } +#else + if (soap_new_block(soap)) + return NULL; + for (;;) + { register int i; + register char *s = (char*)soap_push_block(soap, SOAP_BLKLEN); + if (!s) + { soap_end_block(soap); + return NULL; + } + for (i = 0; i < SOAP_BLKLEN; i++) + { register char d1, d2; + register soap_wchar c = soap_get(soap); + if (soap_isxdigit(c)) + { d1 = (char)c; + c = soap_get(soap); + if (soap_isxdigit(c)) + d2 = (char)c; + else + { soap_end_block(soap); + soap->error = SOAP_TYPE; + return NULL; + } + } + else + { unsigned char *p; + soap_unget(soap, c); + if (n) + *n = soap_size_block(soap, i); + p = (unsigned char*)soap_save_block(soap, NULL, 0); + return p; + } + *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'); + } + } +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putbase64(struct soap *soap, const unsigned char *s, int n) +{ register int i; + register unsigned long m; + char d[4]; + if (!s) + return SOAP_OK; +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { if (!(soap->dom->data = soap_s2base64(soap, s, soap->dom->data, n))) + return soap->error; + return SOAP_OK; + } +#endif + for (; n > 2; n -= 3, s += 3) + { m = s[0]; + m = (m << 8) | s[1]; + m = (m << 8) | s[2]; + for (i = 4; i > 0; m >>= 6) + d[--i] = soap_base64o[m & 0x3F]; + if (soap_send_raw(soap, d, 4)) + return soap->error; + } + if (n > 0) + { m = 0; + for (i = 0; i < n; i++) + m = (m << 8) | *s++; + for (; i < 3; i++) + m <<= 8; + for (i++; i > 0; m >>= 6) + d[--i] = soap_base64o[m & 0x3F]; + for (i = 3; i > n; i--) + d[i] = '='; + if (soap_send_raw(soap, d, 4)) + return soap->error; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +unsigned char* +SOAP_FMAC2 +soap_getbase64(struct soap *soap, int *n, int malloc_flag) +{ +#ifdef WITH_FAST + soap->labidx = 0; + for (;;) + { register int i, k; + register char *s; + if (soap_append_lab(soap, NULL, 2)) + return NULL; + s = soap->labbuf + soap->labidx; + k = 3 * ((soap->lablen - soap->labidx) / 3); + soap->labidx = 3 * (soap->lablen / 3); + if (!s) + return NULL; + for (i = 0; i < k; i += 3) + { register unsigned long m = 0; + register int j = 0; + do + { register soap_wchar c = soap_get(soap); + if (c == '=' || c < 0) + { unsigned char *p; + switch (j) + { case 2: + *s++ = (char)((m >> 4) & 0xFF); + i++; + break; + case 3: + *s++ = (char)((m >> 10) & 0xFF); + *s++ = (char)((m >> 2) & 0xFF); + i += 2; + } + if (n) + *n = (int)(soap->lablen - k + i); + p = (unsigned char*)soap_malloc(soap, soap->lablen - k + i); + if (p) + memcpy(p, soap->labbuf, soap->lablen - k + i); + if (c >= 0) + { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT) + ; + } + soap_unget(soap, c); + return p; + } + c -= '+'; + if (c >= 0 && c <= 79) + { m = (m << 6) + soap_base64i[c]; + j++; + } + } while (j < 4); + *s++ = (char)((m >> 16) & 0xFF); + *s++ = (char)((m >> 8) & 0xFF); + *s++ = (char)(m & 0xFF); + } + } +#else + if (soap_new_block(soap)) + return NULL; + for (;;) + { register int i; + register char *s = (char*)soap_push_block(soap, 3 * SOAP_BLKLEN); /* must be multiple of 3 */ + if (!s) + { soap_end_block(soap); + return NULL; + } + for (i = 0; i < SOAP_BLKLEN; i++) + { register unsigned long m = 0; + register int j = 0; + do + { register soap_wchar c = soap_get(soap); + if (c == '=' || c < 0) + { unsigned char *p; + i *= 3; + switch (j) + { case 2: + *s++ = (char)((m >> 4) & 0xFF); + i++; + break; + case 3: + *s++ = (char)((m >> 10) & 0xFF); + *s++ = (char)((m >> 2) & 0xFF); + i += 2; + } + if (n) + *n = (int)soap_size_block(soap, i); + p = (unsigned char*)soap_save_block(soap, NULL, 0); + if (c >= 0) + { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT) + ; + } + soap_unget(soap, c); + return p; + } + c -= '+'; + if (c >= 0 && c <= 79) + { m = (m << 6) + soap_base64i[c]; + j++; + } + } while (j < 4); + *s++ = (char)((m >> 16) & 0xFF); + *s++ = (char)((m >> 8) & 0xFF); + *s++ = (char)(m & 0xFF); + } + } +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_strdup(struct soap *soap, const char *s) +{ char *t = NULL; + if (s && (t = (char*)soap_malloc(soap, strlen(s) + 1))) + strcpy(t, s); + return t; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_new_block(struct soap *soap) +{ struct soap_blist *p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New block sequence (prev=%p)\n", soap->blist)); + if (!(p = (struct soap_blist*)SOAP_MALLOC(sizeof(struct soap_blist)))) + return SOAP_EOM; + p->next = soap->blist; + p->ptr = NULL; + p->size = 0; + soap->blist = p; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_push_block(struct soap *soap, size_t n) +{ char *p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push block of %u bytes (%u bytes total)\n", (unsigned int)n, (unsigned int)soap->blist->size + (unsigned int)n)); + if (!(p = (char*)SOAP_MALLOC(n + sizeof(char*) + sizeof(size_t)))) + { soap->error = SOAP_EOM; + return NULL; + } + *(char**)p = soap->blist->ptr; + *(size_t*)(p + sizeof(char*)) = n; + soap->blist->ptr = p; + soap->blist->size += n; + return p + sizeof(char*) + sizeof(size_t); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_pop_block(struct soap *soap) +{ char *p; + if (!soap->blist->ptr) + return; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop block\n")); + p = soap->blist->ptr; + soap->blist->size -= *(size_t*)(p + sizeof(char*)); + soap->blist->ptr = *(char**)p; + SOAP_FREE(p); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static void +soap_update_ptrs(struct soap *soap, char *start, char *end, long offset) +{ int i; + register struct soap_ilist *ip; + register struct soap_flist *fp; + register void *p, **q; + for (i = 0; i < SOAP_IDHASH; i++) + for (ip = soap->iht[i]; ip; ip = ip->next) + { if (ip->ptr && (char*)ip->ptr >= start && (char*)ip->ptr < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", ip->id, ip->ptr, (char*)ip->ptr + offset)); + ip->ptr = (char*)ip->ptr + offset; + } + for (q = &ip->link; q; q = (void**)p) + { p = *q; + if (p && (char*)p >= start && (char*)p < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Link update id='%s' %p\n", ip->id, p)); + *q = (char*)p + offset; + } + } + for (q = &ip->copy; q; q = (void**)p) + { p = *q; + if (p && (char*)p >= start && (char*)p < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy chain update id='%s' %p\n", ip->id, p)); + *q = (char*)p + offset; + } + } + for (fp = ip->flist; fp; fp = fp->next) + { if ((char*)fp->ptr >= start && (char*)fp->ptr < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy list update id='%s' %p\n", ip->id, fp)); + fp->ptr = (char*)fp->ptr + offset; + } + } + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +soap_has_copies(struct soap *soap, register const char *start, register const char *end) +{ register int i; + register struct soap_ilist *ip; + register struct soap_flist *fp; + register const char *p; + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { for (p = (const char*)ip->copy; p; p = *(const char**)p) + if (p >= start && p < end) + return SOAP_ERR; + for (fp = ip->flist; fp; fp = fp->next) + if ((const char*)fp->ptr >= start && (const char*)fp->ptr < end) + return SOAP_ERR; + } + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_resolve(struct soap *soap) +{ register int i; + register struct soap_ilist *ip; + register struct soap_flist *fp; + short flag; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data\n")); + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { if (ip->ptr) + { register void *p, **q, *r; + q = (void**)ip->link; + ip->link = NULL; + r = ip->ptr; + DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing link chain to resolve id='%s'\n", ip->id)); + while (q) + { p = *q; + *q = r; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "... link %p -> %p\n", q, r)); + q = (void**)p; + } + } + else if (*ip->id == '#') + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Missing data for id='%s'\n", ip->id)); + strcpy(soap->id, ip->id + 1); + return soap->error = SOAP_MISSING_ID; + } + } + } + do + { flag = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution phase\n")); + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { if (ip->ptr && !soap_has_copies(soap, (const char*)ip->ptr, (const char*)ip->ptr + ip->size)) + { if (ip->copy) + { register void *p, **q = (void**)ip->copy; + DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing copy chain to resolve id='%s'\n", ip->id)); + ip->copy = NULL; + do + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... copy %p -> %p (%u bytes)\n", ip->ptr, q, (unsigned int)ip->size)); + p = *q; + memcpy(q, ip->ptr, ip->size); + q = (void**)p; + } while (q); + flag = 1; + } + for (fp = ip->flist; fp; fp = ip->flist) + { register unsigned int k = fp->level; + register void *p = ip->ptr; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data type=%d location=%p level=%u,%u id='%s'\n", ip->type, p, ip->level, fp->level, ip->id)); + while (ip->level < k) + { register void **q = (void**)soap_malloc(soap, sizeof(void*)); + if (!q) + return soap->error; + *q = p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level, new location=%p holds=%p...\n", q, *q)); + p = (void*)q; + k--; + } + if (fp->fcopy) + fp->fcopy(soap, ip->type, fp->type, fp->ptr, p, ip->size); + else + soap_fcopy(soap, ip->type, fp->type, fp->ptr, p, ip->size); + ip->flist = fp->next; + SOAP_FREE(fp); + flag = 1; + } + } + } + } + } while (flag); +#ifdef SOAP_DEBUG + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { if (ip->copy || ip->flist) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution error: forwarded data for id='%s' could not be propagated, please report this problem to the developers\n", ip->id)); + } + } + } +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution done\n")); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_size_block(struct soap *soap, size_t n) +{ if (soap->blist->ptr) + { soap->blist->size -= *(size_t*)(soap->blist->ptr + sizeof(char*)) - n; + *(size_t*)(soap->blist->ptr + sizeof(char*)) = n; + } + return soap->blist->size; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_first_block(struct soap *soap) +{ char *p, *q, *r; + p = soap->blist->ptr; + if (!p) + return NULL; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "First block\n")); + r = NULL; + do + { q = *(char**)p; + *(char**)p = r; + r = p; + p = q; + } while (p); + soap->blist->ptr = r; + return r + sizeof(char*) + sizeof(size_t); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_next_block(struct soap *soap) +{ char *p; + p = soap->blist->ptr; + if (p) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Next block\n")); + soap->blist->ptr = *(char**)p; + SOAP_FREE(p); + if (soap->blist->ptr) + return soap->blist->ptr + sizeof(char*) + sizeof(size_t); + } + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_block_size(struct soap *soap) +{ return *(size_t*)(soap->blist->ptr + sizeof(char*)); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_end_block(struct soap *soap) +{ struct soap_blist *bp; + char *p, *q; + bp = soap->blist; + if (bp) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of block sequence, free all remaining blocks\n")); + for (p = bp->ptr; p; p = q) + { q = *(char**)p; + SOAP_FREE(p); + } + soap->blist = bp->next; + SOAP_FREE(bp); + } + DBGLOG(TEST, if (soap->blist) SOAP_MESSAGE(fdebug, "Restore previous block sequence\n")); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_save_block(struct soap *soap, char *p, int flag) +{ register size_t n; + register char *q, *s; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Save all blocks in contiguous memory space of %u bytes (%p->%p)\n", (unsigned int)soap->blist->size, soap->blist->ptr, p)); + if (soap->blist->size) + { if (!p) + p = (char*)soap_malloc(soap, soap->blist->size); + if (p) + { for (s = p, q = soap_first_block(soap); q; q = soap_next_block(soap)) + { n = soap_block_size(soap); + if (flag) + soap_update_ptrs(soap, q, q + n, (long)s - (long)q); /* pointers s and q may or may not be related */ + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy %u bytes from %p to %p\n", (unsigned int)n, q, s)); + memcpy(s, q, n); + s += n; + } + } + else + soap->error = SOAP_EOM; + } + soap_end_block(soap); + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putsize(struct soap *soap, const char *type, int size) +{ return soap_putsizes(soap, type, &size, 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putsizes(struct soap *soap, const char *type, const int *size, int dim) +{ return soap_putsizesoffsets(soap, type, size, NULL, dim); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putsizesoffsets(struct soap *soap, const char *type, const int *size, const int *offset, int dim) +{ int i; + if (!type) + return NULL; + if (soap->version == 2) + { sprintf(soap->type, "%s[%d", type, size[0]); + for (i = 1; i < dim; i++) + sprintf(soap->type + strlen(soap->type), " %d", size[i]); + } + else + { if (offset) + { sprintf(soap->type, "%s[%d", type, size[0] + offset[0]); + for (i = 1; i < dim; i++) + sprintf(soap->type + strlen(soap->type), ",%d", size[i] + offset[i]); + } + else + { sprintf(soap->type, "%s[%d", type, size[0]); + for (i = 1; i < dim; i++) + sprintf(soap->type + strlen(soap->type), ",%d", size[i]); + } + strcat(soap->type, "]"); + } + return soap->type; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putoffset(struct soap *soap, int offset) +{ return soap_putoffsets(soap, &offset, 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putoffsets(struct soap *soap, const int *offset, int dim) +{ register int i; + sprintf(soap->arrayOffset, "[%d", offset[0]); + for (i = 1; i < dim; i++) + sprintf(soap->arrayOffset + strlen(soap->arrayOffset), ",%d", offset[i]); + strcat(soap->arrayOffset, "]"); + return soap->arrayOffset; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_size(const int *size, int dim) +{ register int i, n = size[0]; + for (i = 1; i < dim; i++) + n *= size[i]; + return n; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getoffsets(const char *attr, const int *size, int *offset, int dim) +{ register int i, j = 0; + if (offset) + for (i = 0; i < dim && attr && *attr; i++) + { attr++; + j *= size[i]; + j += offset[i] = (int)atol(attr); + attr = strchr(attr, ','); + } + else + for (i = 0; i < dim && attr && *attr; i++) + { attr++; + j *= size[i]; + j += (int)atol(attr); + attr = strchr(attr, ','); + } + return j; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getsize(const char *attr1, const char *attr2, int *j) +{ register int n, k; + char *s; + *j = 0; + if (!*attr1) + return -1; + n = 1; + do + { attr1++; + k = (int)soap_strtol(attr1, &s, 10); + n *= k; + if (k < 0 || n > SOAP_MAXARRAYSIZE || s == attr1) + return -1; + attr1 = strchr(s, ','); + if (!attr1) + attr1 = strchr(s, ' '); + if (attr2 && *attr2) + { attr2++; + *j *= k; + k = (int)soap_strtol(attr2, &s, 10); + *j += k; + if (k < 0) + return -1; + attr2 = s; + } + } while (attr1 && *attr1 != ']'); + return n - *j; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getsizes(const char *attr, int *size, int dim) +{ register int i, k, n; + if (!*attr) + return -1; + i = strlen(attr); + n = 1; + do + { for (i = i-1; i >= 0; i--) + if (attr[i] == '[' || attr[i] == ',' || attr[i] == ' ') + break; + k = (int)atol(attr + i + 1); + n *= size[--dim] = k; + if (k < 0 || n > SOAP_MAXARRAYSIZE) + return -1; + } while (i >= 0 && attr[i] != '['); + return n; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getposition(const char *attr, int *pos) +{ register int i, n; + if (!*attr) + return -1; + n = 0; + i = 1; + do + { pos[n++] = (int)atol(attr + i); + while (attr[i] && attr[i] != ',' && attr[i] != ']') + i++; + if (attr[i] == ',') + i++; + } while (n < SOAP_MAXDIMS && attr[i] && attr[i] != ']'); + return n; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_push_namespace(struct soap *soap, const char *id, const char *ns) +{ register struct soap_nlist *np; + register struct Namespace *p; + np = (struct soap_nlist*)SOAP_MALLOC(sizeof(struct soap_nlist) + strlen(id)); + if (!np) + return soap->error = SOAP_EOM; + np->next = soap->nlist; + soap->nlist = np; + strcpy(np->id, id); + np->level = soap->level; + np->index = -1; + np->ns = NULL; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push namespace binding (level=%u) '%s' '%s'\n", soap->level, id, ns)); + p = soap->local_namespaces; + if (p) + { register short i = 0; + for (; p->id; p++, i++) + { if (p->ns && !strcmp(ns, p->ns)) + { if (p->out) + { SOAP_FREE(p->out); + p->out = NULL; + } + break; + } + if (p->out) + { if (!SOAP_STRCMP(ns, p->out)) + break; + } + else if (p->in) + { if (!soap_tag_cmp(ns, p->in)) + { if ((p->out = (char*)SOAP_MALLOC(strlen(ns) + 1))) + strcpy(p->out, ns); + break; + } + } + } + if (p && p->id) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push OK ('%s' matches '%s' in namespace table)\n", id, p->id)); + np->index = i; + } + } + if (!p || !p->id) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push NOT OK: no match found for '%s' in namespace mapping table (added to stack anyway)\n", ns)); + np->ns = (char*)SOAP_MALLOC(strlen(ns) + 1); + if (!np->ns) + return soap->error = SOAP_EOM; + strcpy(np->ns, ns); + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_pop_namespace(struct soap *soap) +{ register struct soap_nlist *np; + while (soap->nlist && soap->nlist->level >= soap->level) + { np = soap->nlist->next; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Popped namespace binding (level=%u) '%s'\n", soap->level, soap->nlist->id)); + if (soap->nlist->ns) + SOAP_FREE(soap->nlist->ns); + SOAP_FREE(soap->nlist); + soap->nlist = np; + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_match_namespace(struct soap *soap, const char *id1, const char *id2, int n1, int n2) +{ register struct soap_nlist *np = soap->nlist; + while (np && (strncmp(np->id, id1, n1) || np->id[n1])) + np = np->next; + if (np) + { if (np->index < 0 || (np->index >= 0 && soap->local_namespaces[np->index].id && (strncmp(soap->local_namespaces[np->index].id, id2, n2) || soap->local_namespaces[np->index].id[n2]))) + return SOAP_NAMESPACE; + return SOAP_OK; + } + if (n1 == 3 && n1 == n2 && !strcmp(id1, "xml") && !strcmp(id1, id2)) + return SOAP_OK; + return SOAP_SYNTAX_ERROR; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_tag_cmp(const char *s, const char *t) +{ for (;;) + { register int c1 = *s; + register int c2 = *t; + if (!c1 || c1 == '"') + break; + if (c2 != '-') + { if (c1 != c2) + { if (c1 >= 'A' && c1 <= 'Z') + c1 += 'a' - 'A'; + if (c2 >= 'A' && c2 <= 'Z') + c2 += 'a' - 'A'; + } + if (c1 != c2) + { if (c2 != '*') + return 1; + c2 = *++t; + if (!c2) + return 0; + if (c2 >= 'A' && c2 <= 'Z') + c2 += 'a' - 'A'; + for (;;) + { c1 = *s; + if (!c1 || c1 == '"') + break; + if (c1 >= 'A' && c1 <= 'Z') + c1 += 'a' - 'A'; + if (c1 == c2) + if (!soap_tag_cmp(s + 1, t + 1)) + return 0; + s++; + } + break; + } + } + s++; + t++; + } + if (*t == '*' && !t[1]) + return 0; + return *t; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_match_tag(struct soap *soap, const char *tag1, const char *tag2) +{ register const char *s, *t; + if (!tag1 || !tag2 || !*tag2) + return SOAP_OK; + s = strchr(tag1, ':'); + t = strchr(tag2, ':'); + if (t) + { if (s) + { if (t[1] && SOAP_STRCMP(s + 1, t + 1)) + return SOAP_TAG_MISMATCH; + if (t != tag2 && soap_match_namespace(soap, tag1, tag2, s - tag1, t - tag2)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2)); + return SOAP_TAG_MISMATCH; + } + } + else if (SOAP_STRCMP(tag1, t + 1)) + return SOAP_TAG_MISMATCH; + else if (t != tag2 && soap_match_namespace(soap, tag1, tag2, 0, t - tag2)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2)); + return SOAP_TAG_MISMATCH; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags and (default) namespaces match: '%s' '%s'\n", tag1, tag2)); + return SOAP_OK; + } + if (s) + { if (SOAP_STRCMP(s + 1, tag2)) + return SOAP_TAG_MISMATCH; + } + else if (SOAP_STRCMP(tag1, tag2)) + return SOAP_TAG_MISMATCH; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags match: '%s' '%s'\n", tag1, tag2)); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_match_array(struct soap *soap, const char *type) +{ if (*soap->arrayType) + if (soap_match_tag(soap, soap->arrayType, type) + && soap_match_tag(soap, soap->arrayType, "xsd:anyType") + && soap_match_tag(soap, soap->arrayType, "xsd:ur-type") + ) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array type mismatch: '%s' '%s'\n", soap->arrayType, type)); + return SOAP_TAG_MISMATCH; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ + +#ifdef WITH_OPENSSL +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_ssl_server_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *password, const char *cafile, const char *capath, const char *dhfile, const char *randfile, const char *sid) +{ int err; + soap->keyfile = keyfile; + soap->password = password; + soap->cafile = cafile; + soap->capath = capath; + if (dhfile) + { soap->dhfile = dhfile; + soap->rsa = 0; + } + else + { soap->dhfile = NULL; + soap->rsa = 1; + } + soap->randfile = randfile; + soap->require_client_auth = (flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION); + if (!(err = soap->fsslauth(soap))) + if (sid) + SSL_CTX_set_session_id_context(soap->ctx, (unsigned char*)sid, strlen(sid)); + return err; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_ssl_client_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *password, const char *cafile, const char *capath, const char *randfile) +{ soap->keyfile = keyfile; + soap->password = password; + soap->cafile = cafile; + soap->capath = capath; + soap->dhfile = NULL; + soap->rsa = 0; + soap->randfile = randfile; + soap->require_server_auth = (flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION); + return soap->fsslauth(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +static void +ssl_init() +{ static int done = 0; + if (!done) + { done = 1; + SSL_library_init(); +#ifndef WITH_LEAN + SSL_load_error_strings(); +#endif + if (!RAND_load_file("/dev/urandom", 1024)) + { int r; +#ifdef HAVE_RAND_R + unsigned int s = (unsigned int)time(NULL); +#endif + char buf[SOAP_BUFLEN]; + RAND_seed(buf, sizeof(buf)); + while (!RAND_status()) + { +#ifdef HAVE_RAND_R + r = rand_r(&s); +#else + r = rand(); +#endif + RAND_seed(&r, sizeof(int)); + } + } + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static const char * +ssl_error(struct soap *soap, int ret) +{ int err = SSL_get_error(soap->ssl, ret); + const char *msg = soap_str_code(h_ssl_error_codes, err); + if (msg) + strcpy(soap->msgbuf, msg); + else + return ERR_error_string(err, soap->msgbuf); + if (ERR_peek_error()) + { unsigned long r; + strcat(soap->msgbuf, "\n"); + while ((r = ERR_get_error())) + ERR_error_string_n(r, soap->msgbuf + strlen(soap->msgbuf), sizeof(soap->msgbuf) - strlen(soap->msgbuf)); + } + else + { switch (ret) + { case 0: + strcpy(soap->msgbuf, "EOF was observed that violates the protocol. The client probably provided invalid authentication information."); + break; + case -1: + sprintf(soap->msgbuf, "Error observed by underlying BIO: %s", strerror(errno)); + break; + } + } + return soap->msgbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +ssl_password(char *buf, int num, int rwflag, void *userdata) +{ if (num < (int)strlen((char*)userdata) + 1) + return 0; + return strlen(strcpy(buf, (char*)userdata)); +} +#endif + +/******************************************************************************/ +/* This callback is included for future references. It should not be deleted +#ifndef PALM_2 +static DH * +ssl_tmp_dh(SSL *ssl, int is_export, int keylength) +{ static DH *dh512 = NULL; + static DH *dh1024 = NULL; + DH *dh; + switch (keylength) + { case 512: + if (!dh512) + { BIO *bio = BIO_new_file("dh512.pem", "r"); + if (bio) + { dh512 = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + return dh512; + } + } + else + return dh512; + default: + if (!dh1024) + { BIO *bio = BIO_new_file("dh1024.pem", "r"); + if (bio) + { dh1024 = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + } + } + dh = dh1024; + } + return dh; +} +#endif +*/ +/******************************************************************************/ +#ifndef PALM_1 +static int +ssl_auth_init(struct soap *soap) +{ ssl_init(); + if (!soap->ctx) + if (!(soap->ctx = SSL_CTX_new(SSLv23_method()))) + return soap_set_receiver_error(soap, "SSL error", "Can't setup context", SOAP_SSL_ERROR); + if (soap->randfile) + { if (!RAND_load_file(soap->randfile, -1)) + return soap_set_receiver_error(soap, "SSL error", "Can't load randomness", SOAP_SSL_ERROR); + } + if (soap->cafile || soap->capath) + if (!SSL_CTX_load_verify_locations(soap->ctx, soap->cafile, soap->capath)) + return soap_set_receiver_error(soap, "SSL error", "Can't read CA file and/or directory", SOAP_SSL_ERROR); + if (!SSL_CTX_set_default_verify_paths(soap->ctx)) + return soap_set_receiver_error(soap, "SSL error", "Can't read default CA file and/or directory", SOAP_SSL_ERROR); + if (soap->keyfile) + { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile)) + return soap_set_receiver_error(soap, "SSL error", "Can't read certificate key file", SOAP_SSL_ERROR); + if (soap->password) + { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password); + SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password); + if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM)) + return soap_set_receiver_error(soap, "SSL error", "Can't read key file", SOAP_SSL_ERROR); + } + } + if (soap->rsa) + { RSA *rsa = RSA_generate_key(512, RSA_F4, NULL, NULL); + if (!SSL_CTX_set_tmp_rsa(soap->ctx, rsa)) + { if (rsa) + RSA_free(rsa); + return soap_set_receiver_error(soap, "SSL error", "Can't set RSA key", SOAP_SSL_ERROR); + } + RSA_free(rsa); + } + else if (soap->dhfile) + { DH *dh = 0; + BIO *bio; + bio = BIO_new_file(soap->dhfile, "r"); + if (!bio) + return soap_set_receiver_error(soap, "SSL error", "Can't read DH file", SOAP_SSL_ERROR); + dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + if (SSL_CTX_set_tmp_dh(soap->ctx, dh) < 0) + { if (dh) + DH_free(dh); + return soap_set_receiver_error(soap, "SSL error", "Can't set DH parameters", SOAP_SSL_ERROR); + } + DH_free(dh); + } + SSL_CTX_set_options(soap->ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2); + SSL_CTX_set_verify(soap->ctx, soap->require_client_auth ? (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT) : soap->require_server_auth ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, soap->fsslverify); +#if (OPENSSL_VERSION_NUMBER < 0x00905100L) + SSL_CTX_set_verify_depth(soap->ctx, 1); +#else + SSL_CTX_set_verify_depth(soap->ctx, 9); +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +ssl_verify_callback(int ok, X509_STORE_CTX *store) +{ +#ifdef SOAP_DEBUG + if (!ok) + { char data[256]; + X509 *cert = X509_STORE_CTX_get_current_cert(store); + fprintf(stderr, "SSL Verify error with certificate at depth %d: %s\n", X509_STORE_CTX_get_error_depth(store), X509_verify_cert_error_string(X509_STORE_CTX_get_error(store))); + X509_NAME_oneline(X509_get_issuer_name(cert), data, sizeof(data)); + fprintf(stderr, "certificate issuer %s\n", data); + X509_NAME_oneline(X509_get_subject_name(cert), data, sizeof(data)); + fprintf(stderr, "certificate subject %s\n", data); + } +#endif + /* return 1 to always continue, but unsafe progress will be terminated by SSL */ + return ok; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_ssl_accept(struct soap *soap) +{ int i, r; + if (!soap_valid_socket(soap->socket)) + return soap_set_receiver_error(soap, "SSL error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR); + if (!soap->ssl) + { soap->ssl = SSL_new(soap->ctx); + if (!soap->ssl) + return soap_set_receiver_error(soap, "SSL error", "SSL_new() failed in soap_ssl_accept()", SOAP_SSL_ERROR); + } + else + SSL_clear(soap->ssl); + soap->imode |= SOAP_ENC_SSL; + soap->omode |= SOAP_ENC_SSL; +#ifdef WIN32 + { u_long nonblocking = 1; + ioctlsocket((SOAP_SOCKET)soap->socket, FIONBIO, &nonblocking); + } +#else + fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL)|O_NONBLOCK); +#endif + soap->bio = BIO_new_socket((SOAP_SOCKET)soap->socket, BIO_NOCLOSE); + SSL_set_bio(soap->ssl, soap->bio, soap->bio); + i = 100; /* 100 * 0.1 ms retries */ + while ((r = SSL_accept(soap->ssl)) <= 0) + { int err = SSL_get_error(soap->ssl, r); + if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) + { struct timeval timeout; + fd_set fd; + if (i-- <= 0) + break; + timeout.tv_sec = 0; + timeout.tv_usec = 100000; + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->socket, &fd); + r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout); + if (r < 0 && soap_socket_errno != SOAP_EINTR) + { soap->errnum = soap_socket_errno; + return SOAP_EOF; + } + } + else + { soap->errnum = err; + break; + } + } +#ifdef WIN32 + { u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)soap->socket, FIONBIO, &blocking); + } +#else + fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL)&~O_NONBLOCK); +#endif + if (r <= 0) + { soap_set_receiver_error(soap, ssl_error(soap, r), "SSL_accept() failed in soap_ssl_accept()", SOAP_SSL_ERROR); + soap_closesock(soap); + return SOAP_SSL_ERROR; + } + if (soap->require_client_auth) + { X509 *peer; + int err; + if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK) + { soap_closesock(soap); + return soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL certificate presented by peer cannot be verified in soap_ssl_accept()", SOAP_SSL_ERROR); + } + peer = SSL_get_peer_certificate(soap->ssl); + if (!peer) + { soap_closesock(soap); + return soap_set_sender_error(soap, "SSL error", "No SSL certificate was presented by the peer in soap_ssl_accept()", SOAP_SSL_ERROR); + } + X509_free(peer); + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#endif /* WITH_OPENSSL */ + +/******************************************************************************/ +#ifndef PALM_1 +static int +tcp_init(struct soap *soap) +{ soap->errmode = 1; +#ifdef WIN32 + if (tcp_done) + return 0; + else + { WSADATA w; + if (WSAStartup(MAKEWORD(1, 1), &w)) + return -1; + tcp_done = 1; + } +#endif + return 0; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_done(struct soap *soap) +{ +#ifdef SOAP_DEBUG + int i; +#endif + soap_free(soap); + while (soap->clist) + { struct soap_clist *p = soap->clist->next; + SOAP_FREE(soap->clist); + soap->clist = p; + } + soap->keep_alive = 0; /* to force close the socket */ + soap_closesock(soap); +#ifdef WITH_COOKIES + soap_free_cookies(soap); +#endif + while (soap->plugins) + { register struct soap_plugin *p = soap->plugins->next; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Removing plugin '%s'\n", soap->plugins->id)); + if (soap->plugins->fcopy || !soap->copy) + soap->plugins->fdelete(soap, soap->plugins); + SOAP_FREE(soap->plugins); + soap->plugins = p; + } + soap->fplugin = fplugin; + soap->fpost = http_post; + soap->fget = http_get; + soap->fposthdr = http_post_header; + soap->fresponse = http_response; + soap->fparse = http_parse; + soap->fparsehdr = http_parse_header; +#ifndef MAC_CARBON +#ifndef WITH_IPV6 + soap->fresolve = tcp_gethost; +#else + soap->fresolve = NULL; +#endif + soap->faccept = tcp_accept; + soap->fopen = tcp_connect; + soap->fclose = tcp_disconnect; + soap->fclosesocket = tcp_closesocket; + soap->fshutdownsocket = tcp_shutdownsocket; + soap->fsend = fsend; + soap->frecv = frecv; + soap->fpoll = soap_poll; +#else + soap->fpoll = NULL; +#endif + soap->fprepareinit = NULL; + soap->fpreparesend = NULL; + soap->fpreparerecv = NULL; + soap->fignore = NULL; + soap->fserveloop = NULL; +#ifdef WITH_OPENSSL + if (soap->session) + { SSL_SESSION_free(soap->session); + soap->session = NULL; + } +#endif + if (!soap->copy) + { if (soap_valid_socket(soap->master)) + { soap->fclosesocket(soap, (SOAP_SOCKET)soap->master); + soap->master = SOAP_INVALID_SOCKET; + } +#ifdef WITH_OPENSSL + if (soap->ctx) + { SSL_CTX_free(soap->ctx); + soap->ctx = NULL; + } +#endif + } +#ifdef SOAP_DEBUG + for (i = 0; i < SOAP_MAXLOGS; i++) + { soap_close_logfile(soap, i); + if (soap->logfile[i]) + { SOAP_FREE((void*)soap->logfile[i]); + soap->logfile[i] = NULL; + } + } +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_cleanup(struct soap *soap) +{ soap_done(soap); +#ifdef WIN32 + if (!tcp_done) + return; + tcp_done = 0; + WSACleanup(); +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static const char* +tcp_error(struct soap *soap) +{ register const char *msg = NULL; + switch (soap->errmode) + { case 0: + msg = soap_strerror(soap); + break; + case 1: + msg = "WSAStartup failed"; + break; + case 2: + { +#ifndef WITH_LEAN + msg = soap_str_code(h_error_codes, soap->errnum); + if (!msg) +#endif + { sprintf(soap->msgbuf, "TCP error %d", soap->errnum); + msg = soap->msgbuf; + } + } + } + return msg; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static const char* +http_error(struct soap *soap, int status) +{ register const char *msg = NULL; +#ifndef WITH_LEAN + msg = soap_str_code(h_http_error_codes, status); + if (!msg) +#endif + { sprintf(soap->msgbuf, "HTTP error %d", status); + msg = soap->msgbuf; + } + return msg; +} +#endif + +/******************************************************************************/ +/* WR[ */ +#ifndef WITH_IPV6 +/* ]WR */ +#ifndef MAC_CARBON +#ifndef PALM_1 +static int +tcp_gethost(struct soap *soap, const char *addr, struct in_addr *inaddr) +{ unsigned long iadd; + struct hostent hostent, *host = &hostent; +/* WR[ */ +#ifdef VXWORKS + int hostint; + char *addrcopy = (char*)malloc(strlen(addr) + 1); /*copy of addr. */ + /* inet_addr(), and hostGetByName() expect "char *"; addr is a "const char *". */ + strncpy(addrcopy, addr, strlen(addr)+1); + iadd = inet_addr(addrcopy); +#else +/* ]WR */ +#if defined(_AIXVERSION_431) || defined(TRU64) + struct hostent_data ht_data; +#endif + iadd = inet_addr(addr); +/* WR[ */ +#endif +/* ]WR */ + if ((int)iadd != -1) + { memcpy(inaddr, &iadd, sizeof(iadd)); +/* WR[ */ +#ifdef VXWORKS + free(addrcopy); +#endif +/* ]WR */ + return SOAP_OK; + } +#if defined(__GLIBC__) + if (gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &host, &soap->errnum) < 0) + host = NULL; +#elif defined(_AIXVERSION_431) || defined(TRU64) + memset((void*)&ht_data, 0, sizeof(ht_data)); + if (gethostbyname_r(addr, &hostent, &ht_data) < 0) + { host = NULL; + soap->errnum = h_errno; + } +#elif defined(HAVE_GETHOSTBYNAME_R) + host = gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &soap->errnum); +/* WR[ */ +#elif defined(VXWORKS) + /* If the DNS resolver library resolvLib has been configured in the vxWorks + * image, a query for the host IP address is sent to the DNS server, if the + * name was not found in the local host table. */ + hostint = hostGetByName(addrcopy); + if (hostint == ERROR) + { host = NULL; + soap->errnum = soap_errno; + } + free(addrcopy); /*free() is placed after the error checking to assure that + * errno captured is that from hostGetByName() */ +/* ]WR */ +#else + if (!(host = gethostbyname(addr))) + soap->errnum = h_errno; +#endif + if (!host) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Host name not found\n")); + return SOAP_ERR; + } +/* WR[ */ +#ifdef VXWORKS + inaddr->s_addr = hostint; +#else +/* ]WR */ + memcpy(inaddr, host->h_addr, host->h_length); +/* WR[ */ +#endif +/* ]WR */ + return SOAP_OK; +} +#endif +#endif +/* WR[ */ +#endif /* WITH_IPV6 */ +/* ]WR */ + +/******************************************************************************/ +#ifndef MAC_CARBON +#ifndef PALM_1 +static int +tcp_connect(struct soap *soap, const char *endpoint, const char *host, int port) +{ struct sockaddr_in sockaddr; +/* WR[ */ +#ifdef WITH_IPV6 + struct addrinfo *addrinfo; + struct addrinfo hints; + struct addrinfo resaddr; + struct sockaddr_storage addrstorage; + int err; +#endif /* WITH_IPV6 */ +/* ]WR */ + register int fd; +#ifndef WITH_LEAN + int len = SOAP_BUFLEN; + int set = 1; +#endif + if (soap_valid_socket(soap->socket)) + soap->fclosesocket(soap, (SOAP_SOCKET)soap->socket); + soap->socket = SOAP_INVALID_SOCKET; + if (tcp_init(soap)) + { soap_set_sender_error(soap, tcp_error(soap), "TCP initialization failed in tcp_connect()", SOAP_TCP_ERROR); + return -1; + } + soap->errmode = 0; +/* WR[ */ +#ifdef WITH_IPV6 + memset((void*)&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + soap->errmode = 2; + if (soap->proxy_host) + err = getaddrinfo(soap->proxy_host, soap_int2s(soap, soap->proxy_port), &hints, &addrinfo); + else + err = getaddrinfo(host, soap_int2s(soap, port), &hints, &addrinfo); + if (addrinfo) + { resaddr = *addrinfo; + addrstorage = *((struct sockaddr_storage*)addrinfo->ai_addr); + resaddr.ai_addr = (struct sockaddr*)&addrstorage; + freeaddrinfo(addrinfo); + } + if (err) + { soap_set_sender_error(soap, gai_strerror(err), + "TCP getaddrinfo on proxy host failed in tcp_connect()", SOAP_TCP_ERROR); + return -1; + } + fd = (int)socket(resaddr.ai_family, resaddr.ai_socktype, resaddr.ai_protocol); /* modified to use fd */ + soap->errmode = 0; +#else /* WITH_IPV6 */ +/* ]WR */ + fd = (int)socket(AF_INET, SOCK_STREAM, 0); +/* WR[ */ +#endif /* WITH_IPV6 */ +/* ]WR */ + if (fd < 0) + { soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "TCP socket failed in tcp_connect()", SOAP_TCP_ERROR); + return -1; + } +#ifdef SOCKET_CLOSE_ON_EXEC +#ifdef WIN32 +#ifndef UNDER_CE + SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0); +#endif +#else + fcntl (fd, F_SETFD, 1); +#endif +#endif +#ifndef WITH_LEAN + if (soap->connect_flags & SO_LINGER) + { struct linger linger; + memset((void*)&linger, 0, sizeof(linger)); + linger.l_onoff = 1; + linger.l_linger = 0; + if (setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger))) + { soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "TCP setsockopt SO_LINGER failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return -1; + } + } + if ((soap->connect_flags & ~SO_LINGER) && setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, soap->connect_flags & ~SO_LINGER, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "TCP setsockopt failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return -1; + } + if (soap->keep_alive && setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "TCP setsockopt SO_KEEPALIVE failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return -1; + } + if (setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "TCP setsockopt SO_SNDBUF failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return -1; + } + if (setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "TCP setsockopt SO_RCVBUF failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return -1; + } +#ifdef TCP_NODELAY + if (setsockopt((SOAP_SOCKET)fd, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "TCP setsockopt TCP_NODELAY failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return -1; + } +#endif +#endif +/* WR[ */ +#ifndef WITH_IPV6 +/* ]WR */ + memset((void*)&sockaddr, 0, sizeof(sockaddr)); + sockaddr.sin_family = AF_INET; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Open socket %d to host='%s'\n", fd, host)); + soap->errmode = 2; + if (soap->proxy_host) + { if (soap->fresolve(soap, soap->proxy_host, &sockaddr.sin_addr)) + { soap_set_sender_error(soap, tcp_error(soap), "TCP get proxy host by name failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return -1; + } + sockaddr.sin_port = htons((short)soap->proxy_port); + } + else + { if (soap->fresolve(soap, host, &sockaddr.sin_addr)) + { soap_set_sender_error(soap, tcp_error(soap), "TCP get host by name failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return -1; + } + sockaddr.sin_port = htons((short)port); + } + soap->errmode = 0; +/* WR[ */ +#endif /* WITH_IPV6 */ +/* ]WR */ +#ifndef WITH_LEAN + if (soap->connect_timeout) +#if defined(WIN32) + { u_long nonblocking = 1; + ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &nonblocking); + } +/* WR[ */ +#elif defined(VXWORKS) + { vx_nonblocking = TRUE; + ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&vx_nonblocking)); /* modified to use fd */ + } +/* ]WR */ +#else + fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)|O_NONBLOCK); +#endif + else +#if defined(WIN32) + { u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &blocking); + } +/* WR[ */ +#elif defined(VXWORKS) + { vx_nonblocking = FALSE; + ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&vx_nonblocking)); /* modified to use fd */ + } +/* ]WR */ +#else + fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)&~O_NONBLOCK); +#endif +#endif + for (;;) + { +/* WR[ */ +#ifdef WITH_IPV6 + if (connect((SOAP_SOCKET)fd, resaddr.ai_addr, resaddr.ai_addrlen)) /* modified to use fd */ +#else /* WITH_IPV6 */ + if (connect((SOAP_SOCKET)fd, (struct sockaddr*)&sockaddr, sizeof(sockaddr))) +#endif /* WITH_IPV6 */ +/* ]WR */ + { +#ifndef WITH_LEAN + if (soap->connect_timeout && (soap_socket_errno == SOAP_EINPROGRESS || soap_socket_errno == SOAP_EWOULDBLOCK)) + { struct timeval timeout; +#if defined(SOCKLEN_T) + SOCKLEN_T n = sizeof(struct sockaddr_in); +#elif defined(__socklen_t_defined) || defined(_SOCKLEN_T) || defined(CYGWIN) + socklen_t n = sizeof(struct sockaddr_in); +#elif defined(WIN32) || defined(__APPLE__) || defined(HP_UX) || defined(SUN_OS) || defined(OPENSERVER) || defined(TRU64) || defined(VXWORKS) + int n = sizeof(struct sockaddr_in); +#else + size_t n = sizeof(struct sockaddr_in); +#endif + fd_set fds; + if (soap->connect_timeout > 0) + { timeout.tv_sec = soap->connect_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->connect_timeout/1000000; + timeout.tv_usec = -soap->connect_timeout%1000000; + } + FD_ZERO(&fds); + FD_SET((SOAP_SOCKET)fd, &fds); + for (;;) + { int r = select((SOAP_SOCKET)(fd + 1), NULL, &fds, NULL, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n")); + soap_set_sender_error(soap, "Timeout", "TCP connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return -1; + } + if (soap_socket_errno != SOAP_EINTR) + { soap->errnum = soap_socket_errno; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); + soap_set_sender_error(soap, tcp_error(soap), "TCP connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return -1; + } + } + n = sizeof(soap->errnum); + if (!getsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_ERROR, (char*)&soap->errnum, &n) && !soap->errnum) + break; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); + soap_set_sender_error(soap, tcp_error(soap), "TCP connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return -1; + } + else +#endif + if (soap_socket_errno != SOAP_EINTR) + { soap->errnum = soap_socket_errno; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); + soap_set_sender_error(soap, tcp_error(soap), "TCP connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return -1; + } + } + else + break; + } +#ifndef WITH_LEAN + if (soap->connect_timeout) +#if defined(WIN32) + { u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &blocking); + } +/* WR[ */ +#elif defined(VXWORKS) + { vx_nonblocking = FALSE; + ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&vx_nonblocking)); /* modified to use fd */ + } +/* ]WR */ +#else + fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)&~O_NONBLOCK); +#endif +#endif + soap->socket = fd; +#ifdef WITH_OPENSSL + soap->imode &= ~SOAP_ENC_SSL; + soap->omode &= ~SOAP_ENC_SSL; + if (!strncmp(endpoint, "https:", 6)) + { int r; + if (soap->proxy_host) + { unsigned int k = soap->omode; /* make sure we only parse HTTP */ + size_t n = soap->count; /* save the content length */ + soap->omode &= ~0xFF; /* mask IO and ENC */ + soap->omode |= SOAP_IO_BUFFER; + soap_begin_send(soap); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connecting to proxy server\n")); + sprintf(soap->tmpbuf, "CONNECT %s:%d HTTP/%s", host, port, soap->http_version); + if ((soap->error = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return -1; +#ifndef WITH_LEAN + if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761) + { sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd); + strcpy(soap->tmpbuf, "Basic "); + soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, strlen(soap->tmpbuf + 262)); + if ((soap->error = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf))) + return soap->error; + } +#endif + if ((soap->error = soap->fposthdr(soap, NULL, NULL)) + || soap_flush(soap)) + return -1; + soap->omode = k; + k = soap->imode; + soap->imode &= ~0xFF; /* mask IO and ENC */ + if (soap_begin_recv(soap)) + return -1; + soap->imode = k; + soap->count = n; + soap_begin_send(soap); + } + if (!soap->ctx && (soap->error = soap->fsslauth(soap))) + { soap_set_sender_error(soap, "SSL error", "SSL authentication failed in tcp_connect(): check password, key file, and ca file.", SOAP_SSL_ERROR); + return -1; + } + soap->ssl = SSL_new(soap->ctx); + if (!soap->ssl) + { soap->error = SOAP_SSL_ERROR; + return -1; + } + if (soap->session) + { if (!strcmp(soap->session_host, host) && soap->session_port == port) + SSL_set_session(soap->ssl, soap->session); + SSL_SESSION_free(soap->session); + soap->session = NULL; + } + soap->imode |= SOAP_ENC_SSL; + soap->omode |= SOAP_ENC_SSL; + soap->bio = BIO_new_socket((SOAP_SOCKET)fd, BIO_NOCLOSE); + SSL_set_bio(soap->ssl, soap->bio, soap->bio); +#ifndef WITH_LEAN + if (soap->connect_timeout) +#ifdef WIN32 + { u_long nonblocking = 1; + ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &nonblocking); + } +#else + fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)|O_NONBLOCK); +#endif +#endif + for (;;) + { if ((r = SSL_connect(soap->ssl)) <= 0) + { int err = SSL_get_error(soap->ssl, r); + if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) + { soap_set_sender_error(soap, ssl_error(soap, r), "SSL connect failed in tcp_connect()", SOAP_SSL_ERROR); + return -1; + } + if (soap->connect_timeout) + { struct timeval timeout; + fd_set fds; + if (soap->connect_timeout > 0) + { timeout.tv_sec = soap->connect_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->connect_timeout/1000000; + timeout.tv_usec = -soap->connect_timeout%1000000; + } + FD_ZERO(&fds); + FD_SET((SOAP_SOCKET)(soap->socket), &fds); + for (;;) + { int r = select((SOAP_SOCKET)(soap->socket + 1), &fds, NULL, &fds, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n")); + soap_set_sender_error(soap, "Timeout", "TCP connect failed in tcp_connect()", SOAP_TCP_ERROR); + return -1; + } + } + continue; + } + } + break; + } +#ifndef WITH_LEAN + if (soap->connect_timeout) +#ifdef WIN32 + { u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &blocking); + } +#else + fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)&~O_NONBLOCK); +#endif +#endif + if (soap->require_server_auth) + { X509 *peer; + int err; + if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK) + { soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL certificate presented by peer cannot be verified in tcp_connect()", SOAP_SSL_ERROR); + return -1; + } + peer = SSL_get_peer_certificate(soap->ssl); + if (!peer) + { soap_set_sender_error(soap, "SSL error", "No SSL certificate was presented by the peer in tcp_connect()", SOAP_SSL_ERROR); + return -1; + } + X509_NAME_get_text_by_NID(X509_get_subject_name(peer), NID_commonName, soap->msgbuf, sizeof(soap->msgbuf)); + X509_free(peer); + if (soap_tag_cmp(soap->msgbuf, host)) + { soap_set_sender_error(soap, "SSL error", "SSL certificate host name mismatch in tcp_connect()", SOAP_SSL_ERROR); + return -1; + } + } + } +#endif + return fd; +} +#endif +#endif + +/******************************************************************************/ +#ifndef MAC_CARBON +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_bind(struct soap *soap, const char *host, int port, int backlog) +{ struct sockaddr_in sockaddr; +/* WR[ */ +#ifdef WITH_IPV6 + struct addrinfo *addrinfo; + struct addrinfo hints; + struct addrinfo resaddr; + struct sockaddr_storage addrstorage; + int err; +#endif /* WITH_IPV6 */ +/* ]WR */ +#ifndef WITH_LEAN + int len = SOAP_BUFLEN; + int set = 1; +#endif + if (soap_valid_socket(soap->master)) + { soap->fclosesocket(soap, (SOAP_SOCKET)soap->master); + soap->master = SOAP_INVALID_SOCKET; + } + soap->socket = SOAP_INVALID_SOCKET; + soap->errmode = 1; + if (tcp_init(soap)) + { soap_set_receiver_error(soap, tcp_error(soap), "TCP init failed in soap_bind()", SOAP_TCP_ERROR); + return -1; + } +/* WR[ */ +#ifdef WITH_IPV6 + memset((void*)&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + soap->errmode = 2; + if (host) + err = getaddrinfo(host, soap_int2s(soap, port), &hints, &addrinfo); + else + err = getaddrinfo(NULL, soap_int2s(soap, port), &hints, &addrinfo); + if (NULL != addrinfo) + { + resaddr = *addrinfo; + addrstorage = *((struct sockaddr_storage *) addrinfo->ai_addr); + resaddr.ai_addr = (struct sockaddr *) &addrstorage; + freeaddrinfo(addrinfo); + } + if (err) + { soap_set_receiver_error(soap, gai_strerror(err), "TCP getaddrinfo failed in soap_bind()", SOAP_TCP_ERROR); + return -1; + } + soap->errmode = 0; + if ((soap->master = socket(resaddr.ai_family, resaddr.ai_socktype, resaddr.ai_protocol)) < 0) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP socket failed in soap_bind()", SOAP_TCP_ERROR); + return -1; + } +#else /* WITH_IPV6 */ +/* ]WR */ + soap->errmode = 0; + if ((soap->master = (int)socket(AF_INET, SOCK_STREAM, 0)) < 0) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP socket failed in soap_bind()", SOAP_TCP_ERROR); + return -1; + } +/* WR[ */ +#endif /* WITH_IPV6 */ +/* ]WR */ +#ifdef SOCKET_CLOSE_ON_EXEC +#ifdef WIN32 +#ifndef UNDER_CE + SetHandleInformation((HANDLE)soap->master, HANDLE_FLAG_INHERIT, 0); +#endif +#else + fcntl (soap->master, F_SETFD, 1); +#endif +#endif +#ifndef WITH_LEAN + if (soap->bind_flags && setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, soap->bind_flags, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt failed in soap_bind()", SOAP_TCP_ERROR); + return -1; + } + if (soap->keep_alive && setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt SO_KEEPALIVE failed in soap_bind()", SOAP_TCP_ERROR); + return -1; + } + if (setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt SO_SNDBUF failed in soap_bind()", SOAP_TCP_ERROR); + return -1; + } + if (setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt SO_RCVBUF failed in soap_bind()", SOAP_TCP_ERROR); + return -1; + } +#ifdef TCP_NODELAY + if (setsockopt((SOAP_SOCKET)soap->master, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt TCP_NODELAY failed in soap_bind()", SOAP_TCP_ERROR); + return -1; + } +#endif +#endif +/* WR[ */ +#ifdef WITH_IPV6 + soap->errmode = 0; + if (bind(soap->master, resaddr.ai_addr, resaddr.ai_addrlen) || listen(soap->master, backlog)) + { + soap->errnum = soap_socket_errno; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n")); + soap_closesock(soap); + soap_set_receiver_error(soap, tcp_error(soap), "TCP bind failed in soap_bind()", SOAP_TCP_ERROR); + return -1; + } +#else /* WITH_IPV6 */ +/* ]WR */ + memset((void*)&sockaddr, 0, sizeof(sockaddr)); + sockaddr.sin_family = AF_INET; + soap->errmode = 2; + if (host) + { if (soap->fresolve(soap, host, &sockaddr.sin_addr)) + { soap_set_receiver_error(soap, tcp_error(soap), "TCP get host by name failed in soap_bind()", SOAP_TCP_ERROR); + return -1; + } + } + else + sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); + sockaddr.sin_port = htons((short)port); + soap->errmode = 0; + if (bind((SOAP_SOCKET)soap->master, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) || listen((SOAP_SOCKET)soap->master, backlog)) + { soap->errnum = soap_socket_errno; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n")); + soap_closesock(soap); + soap_set_receiver_error(soap, tcp_error(soap), "TCP bind failed in soap_bind()", SOAP_TCP_ERROR); + return -1; + } +/* WR[ */ +#endif /* WITH_IPV6 */ +/* ]WR */ +#ifdef WITH_OPENSSL + if (!soap->ctx && (soap->error = soap->fsslauth(soap))) + return -1; +#endif + return soap->master; +} +#endif +#endif + +/******************************************************************************/ +#ifndef MAC_CARBON +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_poll(struct soap *soap) +{ +#ifndef WITH_LEAN + struct timeval timeout; + fd_set sfd,rfd; + int r; + timeout.tv_sec = 0; + timeout.tv_usec = 0; + FD_ZERO(&rfd); + FD_ZERO(&sfd); + if (soap->socket >= 0) + { FD_SET(soap->socket, &rfd); + FD_SET(soap->socket, &sfd); + r = select(soap->socket + 1, &rfd, &sfd, NULL, &timeout); + } + else if (soap->master >= 0) + { FD_SET(soap->master, &rfd); + r = select(soap->master + 1, &rfd, &sfd, NULL, &timeout); + } + else + { FD_SET(soap->sendfd, &sfd); + FD_SET(soap->recvfd, &rfd); + r = select((soap->sendfd > soap->recvfd ? soap->sendfd : soap->recvfd) + 1, &rfd, &sfd, NULL, &timeout); + } + if (r > 0) + { +#ifdef WITH_OPENSSL + if (soap->ssl) + { if ((soap->socket >= 0) && FD_ISSET(soap->socket, &rfd)) + { char buf = '\0'; + if (SSL_peek(soap->ssl, &buf, 1) <= 0) + return SOAP_EOF; + } + } +#endif + return SOAP_OK; + } + if (r < 0 && (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) && soap_socket_errno != SOAP_EINTR) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "select failed in soap_poll()", SOAP_TCP_ERROR); + return soap->error = SOAP_TCP_ERROR; + } + else + soap->errnum = soap_errno; + return SOAP_EOF; +#else + return SOAP_OK; +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef MAC_CARBON +#ifndef PALM_1 +static int +tcp_accept(struct soap *soap, int s, struct sockaddr *a, int *n) +{ int fd; +#if defined(SOCKLEN_T) + fd = (int)accept((SOAP_SOCKET)s, a, (SOCKLEN_T*)n); +#elif defined(__socklen_t_defined) || defined(_SOCKLEN_T) || defined(CYGWIN) + fd = (int)accept((SOAP_SOCKET)s, a, (socklen_t*)n); +#elif defined(WIN32) || defined(__APPLE__) || defined(HP_UX) || defined(SUN_OS) || defined(OPENSERVER) || defined(TRU64) || defined(VXWORKS) + fd = (int)accept((SOAP_SOCKET)s, a, n); +#else + fd = (int)accept((SOAP_SOCKET)s, a, (size_t*)n); +#endif +#ifdef SOCKET_CLOSE_ON_EXEC +#ifdef WIN32 +#ifndef UNDER_CE + SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0); +#endif +#else + fcntl(fd, F_SETFD, FD_CLOEXEC); +#endif +#endif + return fd; +} +#endif +#endif + +/******************************************************************************/ +#ifndef MAC_CARBON +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_accept(struct soap *soap) +{ +/* WR[ */ +#ifdef WITH_IPV6 + struct sockaddr_storage sockaddr; +#else /* WITH_IPV6 */ +/* ]WR */ + struct sockaddr_in sockaddr; +/* WR[ */ +#endif +/* ]WR */ + int n = (int)sizeof(sockaddr); +#ifndef WITH_LEAN + int len = SOAP_BUFLEN; + int set = 1; +#endif + soap->error = SOAP_OK; + memset((void*)&sockaddr, 0, sizeof(sockaddr)); + soap->socket = SOAP_INVALID_SOCKET; + soap->errmode = 0; + if (soap_valid_socket(soap->master)) + { for (;;) + { +#ifndef WITH_LEAN + if (soap->accept_timeout) + { struct timeval timeout; + fd_set fd; + if (soap->accept_timeout > 0) + { timeout.tv_sec = soap->accept_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->accept_timeout/1000000; + timeout.tv_usec = -soap->accept_timeout%1000000; + } + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->master, &fd); + for (;;) + { int r = select((SOAP_SOCKET)(soap->master + 1), &fd, &fd, NULL, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + soap_set_receiver_error(soap, "Timeout", "TCP accept failed in soap_accept()", SOAP_TCP_ERROR); + return -1; + } + if (soap_socket_errno != SOAP_EINTR) + { soap->errnum = soap_socket_errno; + soap_closesock(soap); + soap_set_sender_error(soap, tcp_error(soap), "TCP accept failed in soap_accept()", SOAP_TCP_ERROR); + return -1; + } + } +#if defined(WIN32) + { u_long nonblocking = 1; + ioctlsocket((SOAP_SOCKET)soap->master, FIONBIO, &nonblocking); + } +#elif defined(VXWORKS) + { vx_nonblocking = TRUE; + ioctl((SOAP_SOCKET)soap->master, FIONBIO, (int)(&vx_nonblocking)); + } +#else + fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL)|O_NONBLOCK); +#endif + } + else +#if defined(WIN32) + { u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)soap->master, FIONBIO, &blocking); + } +/* WR[ */ +#elif defined(VXWORKS) + { vx_nonblocking = FALSE; + ioctl((SOAP_SOCKET)soap->master, FIONBIO, (int)(&vx_nonblocking)); + } +/* ]WR */ +#else + fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL)&~O_NONBLOCK); +#endif +#endif + if ((soap->socket = soap->faccept(soap, soap->master, (struct sockaddr*)&sockaddr, &n)) >= 0) + { +/* WR[ */ +#ifdef WITH_IPV6 +/* Use soap->host to store the numeric form of the remote host */ + getnameinfo((struct sockaddr*)&sockaddr, n, soap->host, sizeof(soap->host), NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket %d from %s\n", soap->socket, soap->host)); + soap->ip = 0; /* info stored in soap->host */ + soap->port = 0; /* info stored in soap->host */ +#else /* WITH_IPV6 */ +/* ]WR */ + soap->ip = ntohl(sockaddr.sin_addr.s_addr); + soap->port = (int)ntohs(sockaddr.sin_port); /* does not return port number on some systems */ + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket %d at port %d from IP %d.%d.%d.%d\n", soap->socket, soap->port, (int)(soap->ip>>24)&0xFF, (int)(soap->ip>>16)&0xFF, (int)(soap->ip>>8)&0xFF, (int)soap->ip&0xFF)); +/* WR[ */ +#endif /* WITH_IPV6 */ +/* ]WR */ + soap->keep_alive = ((soap->imode & SOAP_IO_KEEPALIVE) != 0); +#ifndef WITH_LEAN + if (soap->accept_flags & SO_LINGER) + { struct linger linger; + memset((void*)&linger, 0, sizeof(linger)); + linger.l_onoff = 1; + linger.l_linger = 0; + if (setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt SO_LINGER failed in soap_accept()", SOAP_TCP_ERROR); + return -1; + } + } + if ((soap->accept_flags & ~SO_LINGER) && setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, soap->accept_flags & ~SO_LINGER, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt failed in soap_accept()", SOAP_TCP_ERROR); + return -1; + } + if (soap->keep_alive && setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt SO_KEEPALIVE failed in soap_accept()", SOAP_TCP_ERROR); + return -1; + } + if (setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt SO_SNDBUF failed in soap_accept()", SOAP_TCP_ERROR); + return -1; + } + if (setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt SO_RCVBUF failed in soap_accept()", SOAP_TCP_ERROR); + return -1; + } +#ifdef TCP_NODELAY + if (setsockopt((SOAP_SOCKET)soap->socket, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt TCP_NODELAY failed in soap_accept()", SOAP_TCP_ERROR); + return -1; + } +#endif +#endif + if (soap->accept_timeout) + { +#if defined(WIN32) + u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)soap->master, FIONBIO, &blocking); + ioctlsocket((SOAP_SOCKET)soap->socket, FIONBIO, &blocking); +/* WR[ */ +#elif defined(VXWORKS) + vx_nonblocking = FALSE; + ioctl((SOAP_SOCKET)soap->master, FIONBIO, (int)(&vx_nonblocking)); + ioctl((SOAP_SOCKET)soap->socket, FIONBIO, (int)(&vx_nonblocking)); +/* ]WR */ +#elif defined(PALM) + fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL,0)&~O_NONBLOCK); + fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL,0)&~O_NONBLOCK); +#elif defined(SYMBIAN) + long blocking = 0; + ioctl((SOAP_SOCKET)soap->master, 0/*FIONBIO*/, &blocking); +#else + fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL)&~O_NONBLOCK); + fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL)&~O_NONBLOCK); +#endif + } + return soap->socket; + } + if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EAGAIN) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP accept failed in soap_accept()", SOAP_TCP_ERROR); + return -1; + } + } + } + else + { soap_set_receiver_error(soap, tcp_error(soap), "TCP no master socket in soap_accept()", SOAP_TCP_ERROR); + return -1; + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef MAC_CARBON +#ifndef PALM_1 +static int +tcp_disconnect(struct soap *soap) +{ +#ifdef WITH_OPENSSL + if (soap->ssl) + { int r, s = 0; + if (soap->session) + SSL_SESSION_free(soap->session); + if (*soap->host) + { soap->session = SSL_get1_session(soap->ssl); + if (soap->session) + { strcpy(soap->session_host, soap->host); + soap->session_port = soap->port; + } + } + r = SSL_shutdown(soap->ssl); + if (r != 1) + { s = ERR_get_error(); + if (s) + { if (soap_valid_socket(soap->socket)) + { soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 1); + soap->socket = SOAP_INVALID_SOCKET; + } + r = SSL_shutdown(soap->ssl); + } + } + DBGLOG(TEST, if (s) SOAP_MESSAGE(fdebug, "Shutdown failed: %d\n", SSL_get_error(soap->ssl, r))); + SSL_free(soap->ssl); + soap->ssl = NULL; + if (s) + return SOAP_SSL_ERROR; + ERR_remove_state(0); + } +#endif + if (soap_valid_socket(soap->socket)) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Closing socket %d\n", soap->socket)); + soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 2); + soap->fclosesocket(soap, (SOAP_SOCKET)soap->socket); + soap->socket = SOAP_INVALID_SOCKET; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef MAC_CARBON +#ifndef PALM_1 +static int +tcp_closesocket(struct soap *soap, SOAP_SOCKET fd) +{ return closesocket(fd); +} +#endif +#endif + +/******************************************************************************/ +#ifndef MAC_CARBON +#ifndef PALM_1 +static int +tcp_shutdownsocket(struct soap *soap, SOAP_SOCKET fd, int how) +{ return shutdown(fd, how); +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_closesock(struct soap *soap) +{ register int status = soap->error; +#ifndef MAC_CARBON + if (status == SOAP_EOF || status == SOAP_TCP_ERROR || status == SOAP_SSL_ERROR || !soap->keep_alive) + { if ((soap->error = soap->fclose(soap))) + return soap->error; + soap->socket = SOAP_INVALID_SOCKET; + } +#endif +#ifdef WITH_ZLIB + if (soap->zlib_state == SOAP_ZLIB_DEFLATE) + deflateEnd(&soap->d_stream); + else if (soap->zlib_state == SOAP_ZLIB_INFLATE) + inflateEnd(&soap->d_stream); + soap->zlib_state = SOAP_ZLIB_NONE; +#endif + return soap->error = status; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_hash(register const char *s) +{ register size_t h = 0; + while (*s) + h = 65599*h + *s++; + return h % SOAP_IDHASH; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static void +soap_init_pht(struct soap *soap) +{ register int i; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing pointer hashtable\n")); + for (i = 0; i < (int)SOAP_PTRHASH; i++) + soap->pht[i] = NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_new() +{ struct soap *soap = (struct soap*)SOAP_MALLOC(sizeof(struct soap)); + if (soap) + soap_init(soap); + return soap; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_new1(int mode) +{ return soap_new2(mode, mode); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_new2(int imode, int omode) +{ struct soap *soap = (struct soap*)SOAP_MALLOC(sizeof(struct soap)); + if (soap) + soap_init2(soap, imode, omode); + return soap; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static void +soap_free_pht(struct soap *soap) +{ register struct soap_plist *pp, *next; + register int i; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free pointer hashtable\n")); + for (i = 0; i < (int)SOAP_PTRHASH; i++) + { for (pp = soap->pht[i]; pp; pp = next) + { next = pp->next; + SOAP_FREE(pp); + } + soap->pht[i] = NULL; + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_embed(struct soap *soap, const void *p, const struct soap_array *a, int n, const char *tag, int type) +{ register int i; + struct soap_plist *pp; + if (soap->version != 1) + soap->encoding = 1; + if (a) + i = soap_array_pointer_lookup(soap, p, a, n, type, &pp); + else + i = soap_pointer_lookup(soap, p, type, &pp); + if (i) + { if (soap_is_embedded(soap, pp) + || soap_is_single(soap, pp)) + return 0; + soap_set_embedded(soap, pp); + } + return i; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_pointer_lookup(struct soap *soap, const void *p, int type, struct soap_plist **ppp) +{ register struct soap_plist *pp; + *ppp = NULL; + if (p) + for (pp = soap->pht[soap_hash_ptr(p)]; pp; pp = pp->next) + if (pp->ptr == p && pp->type == type) + { *ppp = pp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d id=%d\n", p, type, pp->id)); + return pp->id; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d: not found\n", p, type)); + return 0; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_pointer_enter(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp) +{ register int h; + register struct soap_plist *pp = *ppp = (struct soap_plist*)SOAP_MALLOC(sizeof(struct soap_plist)); + if (!pp) + return 0; + if (a) + h = soap_hash_ptr(a->__ptr); + else + h = soap_hash_ptr(p); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pointer enter location=%p array=%p size=%d dim=%d type=%d id=%lu\n", p, a?a->__ptr:NULL, a?a->__size:0, n, type, soap->idnum+1)); + pp->next = soap->pht[h]; + pp->type = type; + pp->mark1 = 0; + pp->mark2 = 0; + pp->ptr = p; + pp->array = a; + soap->pht[h] = pp; + pp->id = ++soap->idnum; + return pp->id; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_array_pointer_lookup(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp) +{ register struct soap_plist *pp; + *ppp = NULL; + if (!p || !a->__ptr) + return 0; + for (pp = soap->pht[soap_hash_ptr(a->__ptr)]; pp; pp = pp->next) + { if (pp->type == type && pp->array && pp->array->__ptr == a->__ptr) + { register int i; + for (i = 0; i < n; i++) + if (((const int*)&pp->array->__size)[i] != ((const int*)&a->__size)[i]) + break; + if (i == n) + { *ppp = pp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d id=%d\n", a->__ptr, type, pp->id)); + return pp->id; + } + } + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d: not found\n", a->__ptr, type)); + return 0; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_begin_count(struct soap *soap) +{ soap_clr_attr(soap); + soap_set_local_namespaces(soap); +#ifndef WITH_LEANER + if ((soap->mode & SOAP_ENC_DIME) || (soap->omode & SOAP_ENC_DIME)) + soap->mode = soap->omode | SOAP_IO_LENGTH | SOAP_ENC_DIME; + else +#endif + { soap->mode = soap->omode; + if ((soap->mode & SOAP_IO) == SOAP_IO_STORE + || (((soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_ENC_XML)) && !soap->fpreparesend)) + soap->mode &= ~SOAP_IO_LENGTH; + else + soap->mode |= SOAP_IO_LENGTH; + } + if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH) + { if (!(soap->mode & SOAP_ENC_DIME)) + soap->mode &= ~SOAP_IO_LENGTH; + if (soap->mode & SOAP_ENC_XML) + soap->mode |= SOAP_IO_BUFFER; + else + soap->mode |= SOAP_IO_STORE; + } + if (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH)) + soap->mode |= SOAP_XML_TREE; +#ifndef WITH_LEANER + if (soap->mode & SOAP_ENC_MIME) + soap_select_mime_boundary(soap); + soap->dime.list = soap->dime.last; /* keep track of last DIME attachment */ +#endif + soap->count = 0; + soap->ns = 0; + soap->null = 0; + soap->position = 0; + soap->mustUnderstand = 0; + soap->encoding = 0; + soap->part = SOAP_BEGIN; + soap->idnum = 0; + soap->dime.count = 0; /* count # of attachments */ + soap->dime.size = 0; /* accumulate total size of attachments */ + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin count phase (socket=%d mode=%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count)); + if (soap->fprepareinit && (soap->mode & SOAP_IO) != SOAP_IO_STORE) + soap->fprepareinit(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_begin_send(struct soap *soap) +{ soap->error = SOAP_OK; + soap_clr_attr(soap); + soap_set_local_namespaces(soap); + soap->mode = (soap->omode & ~SOAP_IO_LENGTH) | (soap->mode & SOAP_ENC_DIME); + if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH) + { if (soap->mode & SOAP_ENC_XML) + soap->mode |= SOAP_IO_BUFFER; + else + soap->mode |= SOAP_IO_STORE; + } + if ((soap->mode & SOAP_IO) == SOAP_IO_FLUSH && soap_valid_socket(soap->socket)) + { if (soap->count || (soap->mode & SOAP_ENC_XML)) + soap->mode |= SOAP_IO_BUFFER; + else + soap->mode |= SOAP_IO_STORE; + } + if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) + soap_new_block(soap); + if (!(soap->mode & SOAP_IO_KEEPALIVE)) + soap->keep_alive = 0; + if (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH)) + soap->mode |= SOAP_XML_TREE; +#ifndef WITH_LEANER + if (soap->mode & SOAP_ENC_MIME) + soap_select_mime_boundary(soap); +#endif +#ifdef WIN32 +#ifndef UNDER_CE +#ifndef WITH_FASTCGI + if (!soap_valid_socket(soap->socket)) /* Set win32 stdout or soap->sendfd to BINARY, e.g. to support DIME */ +#ifdef __BORLANDC__ + setmode((SOAP_SOCKET)soap->sendfd, O_BINARY); +#else + _setmode((SOAP_SOCKET)soap->sendfd, _O_BINARY); +#endif +#endif +#endif +#endif + if (soap->mode & SOAP_IO) + { soap->bufidx = 0; + soap->buflen = 0; + } + soap->chunksize = 0; + soap->ns = 0; + soap->null = 0; + soap->position = 0; + soap->mustUnderstand = 0; + soap->encoding = 0; + soap->part = SOAP_BEGIN; + soap->idnum = 0; + soap->level = 0; +#ifdef WITH_ZLIB + soap->z_ratio_out = 1.0; + if ((soap->mode & SOAP_ENC_ZLIB) && soap->zlib_state != SOAP_ZLIB_DEFLATE) + { +#ifdef WITH_GZIP + memcpy(soap->z_buf, "\37\213\10\0\0\0\0\0\0\377", 10); + soap->d_stream.next_out = (Byte*)soap->z_buf + 10; + soap->d_stream.avail_out = SOAP_BUFLEN - 10; + soap->z_crc = crc32(0L, NULL, 0); + if (deflateInit2(&soap->d_stream, soap->z_level, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY) != Z_OK) +#else + soap->d_stream.next_out = (Byte*)soap->z_buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + if (deflateInit(&soap->d_stream, soap->z_level) != Z_OK) +#endif + return soap->error = SOAP_ZLIB_ERROR; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflate initialized\n")); + soap->zlib_state = SOAP_ZLIB_DEFLATE; + } +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin send phase (socket=%d mode=%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count)); + if (soap->fprepareinit && (soap->mode & SOAP_IO) == SOAP_IO_STORE) + soap->fprepareinit(soap); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_embedded(struct soap *soap, const void *p, int t) +{ struct soap_plist *pp; + if (soap_pointer_lookup(soap, p, t, &pp)) + { pp->mark1 = 1; + pp->mark2 = 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded %p type=%d mark set to 1\n", p, t)); + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_reference(struct soap *soap, const void *p, int t) +{ struct soap_plist *pp; + if (!p || (soap->mode & SOAP_XML_TREE)) + return 1; + if (soap_pointer_lookup(soap, p, t, &pp)) + { if (pp->mark1 == 0) + { pp->mark1 = 2; + pp->mark2 = 2; + } + } + else if (soap_pointer_enter(soap, p, NULL, 0, t, &pp)) + { pp->mark1 = 0; + pp->mark2 = 0; + } + else + return 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reference %p type=%d (%d %d)\n", p, t, (int)pp->mark1, (int)pp->mark2)); + return pp->mark1; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_array_reference(struct soap *soap, const void *p, const struct soap_array *a, int n, int t) +{ register int i; + struct soap_plist *pp; + if (!p) + return 1; + i = soap_array_pointer_lookup(soap, p, a, n, t, &pp); + if (i) + { if (pp->mark1 == 0) + { pp->mark1 = 2; + pp->mark2 = 2; + } + } + else if (!soap_pointer_enter(soap, p, a, n, t, &pp)) + return 1; + else + { pp->mark1 = 0; + pp->mark2 = 0; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array reference %p ptr=%p dim=%d type=%d (%d %d)\n", p, a->__ptr, n, t, (int)pp->mark1, (int)pp->mark2)); + return pp->mark1; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_embedded_id(struct soap *soap, int id, const void *p, int t) +{ struct soap_plist *pp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id %p type=%d id=%d\n", p, t, id)); + if (soap->mode & SOAP_XML_TREE) + return id; + if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER) + { if (id < 0) + { id = soap_pointer_lookup(soap, p, t, &pp); + if (id) + { if (soap->mode & SOAP_IO_LENGTH) + pp->mark1 = 2; + else + pp->mark2 = 2; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id multiref id=%d %p type=%d = (%d %d)\n", id, p, t, (int)pp->mark1, (int)pp->mark2)); + } + return -1; + } + return id; + } + if (id < 0) + id = soap_pointer_lookup(soap, p, t, &pp); + else if (id && !soap_pointer_lookup(soap, p, t, &pp)) + return 0; + if (id && pp) + { if (soap->mode & SOAP_IO_LENGTH) + pp->mark1 = 1; + else + pp->mark2 = 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id embedded ref id=%d %p type=%d = (%d %d)\n", id, p, t, (int)pp->mark1, (int)pp->mark2)); + } + return id; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_is_embedded(struct soap *soap, struct soap_plist *pp) +{ if (!pp) + return 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Is embedded? %d %d\n", (int)pp->mark1, (int)pp->mark2)); + if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER) + { if (soap->mode & SOAP_IO_LENGTH) + return pp->mark1 != 0; + return pp->mark2 != 0; + } + if (soap->mode & SOAP_IO_LENGTH) + return pp->mark1 == 1; + return pp->mark2 == 1; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_is_single(struct soap *soap, struct soap_plist *pp) +{ if (soap->part == SOAP_IN_HEADER) + return 1; + if (!pp) + return 0; + if (soap->mode & SOAP_IO_LENGTH) + return pp->mark1 == 0; + return pp->mark2 == 0; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_embedded(struct soap *soap, struct soap_plist *pp) +{ if (!pp) + return; + if (soap->mode & SOAP_IO_LENGTH) + pp->mark1 = 1; + else + pp->mark2 = 1; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_dime(struct soap *soap, const char *tag, int id, const void *p, const struct soap_array *a, const char *aid, const char *atype, const char *aoptions, int n, const char *type, int t) +{ struct soap_plist *pp; + if (!p || !a->__ptr || (!aid && !atype)) + return soap_element_id(soap, tag, id, p, a, n, type, t); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attachment tag='%s' id='%s' (%d) type='%s'\n", tag, aid?aid:"", id, atype?atype:"")); + if (id < 0) + id = soap_array_pointer_lookup(soap, p, a, n, t, &pp); + if (!aid) + { sprintf(soap->tmpbuf, soap->dime_id_format, id); + aid = soap_strdup(soap, soap->tmpbuf); + } + if (soap_element_href(soap, tag, 0, "href", aid)) + return soap->error; + if (soap->mode & SOAP_IO_LENGTH) + { if (pp->mark1 != 3) + { struct soap_multipart *content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, (char*)a->__ptr, a->__size); + if (!content) + return soap->error = SOAP_EOM; + content->id = aid; + content->type = atype; + content->options = aoptions; + pp->mark1 = 3; + } + } + else + pp->mark2 = 3; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static void +soap_init_iht(struct soap *soap) +{ register int i; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing ID hashtable\n")); + for (i = 0; i < SOAP_IDHASH; i++) + soap->iht[i] = NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static void +soap_free_iht(struct soap *soap) +{ register int i; + register struct soap_ilist *ip, *p; + register struct soap_flist *fp, *fq; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free ID hashtable\n")); + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = p) + { for (fp = ip->flist; fp; fp = fq) + { fq = fp->next; + SOAP_FREE(fp); + } + p = ip->next; + SOAP_FREE(ip); + } + soap->iht[i] = NULL; + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +static struct soap_ilist * +soap_hlookup(struct soap *soap, const char *id) +{ register struct soap_ilist *ip; + for (ip = soap->iht[soap_hash(id)]; ip; ip = ip->next) + if (!strcmp(ip->id, id)) + return ip; + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +struct soap_ilist * +SOAP_FMAC2 +soap_lookup(struct soap *soap, const char *id) +{ register struct soap_ilist *ip; + ip = soap_hlookup(soap, id); +#ifndef WITH_LEANER + if (!ip && *id != '#' && !strchr(id, ':')) /* try content id "cid:" with DIME attachments */ + { char cid[SOAP_TAGLEN]; + strcpy(cid, "cid:"); + strncat(cid + 4, id, sizeof(cid) - 5); + cid[sizeof(cid) - 1] = '\0'; + ip = soap_hlookup(soap, cid); + } +#endif + return ip; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +struct soap_ilist * +SOAP_FMAC2 +soap_enter(struct soap *soap, const char *id) +{ register size_t h; + register struct soap_ilist *ip; + ip = (struct soap_ilist*)SOAP_MALLOC(sizeof(struct soap_ilist) + strlen(id)); + if (ip) + { h = soap_hash(id); + strcpy(ip->id, id); + ip->next = soap->iht[h]; + soap->iht[h] = ip; + return ip; + } + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_malloc(struct soap *soap, size_t n) +{ register char *p; + if (!n) + return NULL; + if (!soap) + return SOAP_MALLOC(n); + n += (-(long)n) & 7; + if (!(p = (char*)SOAP_MALLOC(n + sizeof(void*) + sizeof(size_t)))) + { soap->error = SOAP_EOM; + return NULL; + } + /* keep chain of alloced cells for later destruction */ + soap->alloced = 1; + *(void**)(p + n) = soap->alist; + *(size_t*)(p + n + sizeof(void*)) = n; + soap->alist = p + n; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Malloc %u bytes at location %p\n", (unsigned int)n, p)); + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_dealloc(struct soap *soap, void *p) +{ if (!soap) + return; + if (p) + { register char **q; + for (q = (char**)&soap->alist; *q; q = *(char***)q) + { if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*)))) + { *q = **(char***)q; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Freed data at %p\n", p)); + SOAP_FREE(p); + return; + } + } + soap_delete(soap, p); + } + else + { register char *q; + while (soap->alist) + { q = (char*)soap->alist; + soap->alist = *(void**)q; + q -= *(size_t*)(q + sizeof(void*)); + SOAP_FREE(q); + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Dealloc all data done\n")); + } + /* we must assume these were deallocated: */ + soap->action = NULL; + soap->fault = NULL; + soap->header = NULL; + soap->authrealm = NULL; +#ifndef WITH_LEANER + soap_clr_mime(soap); +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_delete(struct soap *soap, void *p) +{ register struct soap_clist **cp = &soap->clist; + if (p) + { while (*cp) + { if (p == (*cp)->ptr) + { register struct soap_clist *q = *cp; + *cp = q->next; + q->fdelete(q); + SOAP_FREE(q); + return; + } + cp = &(*cp)->next; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: address not in list\n", p)); + } + else + { while (*cp) + { register struct soap_clist *q = *cp; + *cp = q->next; + if (q->ptr == (void*)soap->fault) + soap->fault = NULL; /* this was deallocated */ + else if (q->ptr == (void*)soap->header) + soap->header = NULL; /* this was deallocated */ + q->fdelete(q); + SOAP_FREE(q); + } + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +struct soap_clist * +SOAP_FMAC2 +soap_link(struct soap *soap, void *p, int t, int n, void (*fdelete)(struct soap_clist*)) +{ register struct soap_clist *cp; + if ((cp = (struct soap_clist*)SOAP_MALLOC(sizeof(struct soap_clist)))) + { cp->next = soap->clist; + cp->type = t; + cp->size = n; + cp->ptr = p; + cp->fdelete = fdelete; + soap->clist = cp; + } + return cp; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_unlink(struct soap *soap, const void *p) +{ register char **q; + register struct soap_clist **cp; + if (!soap || !p) + return; + for (q = (char**)&soap->alist; *q; q = *(char***)q) + { if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*)))) + { *q = **(char***)q; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked data %p\n", p)); + return; + } + } + for (cp = &soap->clist; *cp; cp = &(*cp)->next) + { if (p == (*cp)->ptr) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked class instance %p\n", p)); + q = (char**)*cp; + *cp = (*cp)->next; + SOAP_FREE(q); + return; + } + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_lookup_type(struct soap *soap, const char *id) +{ register struct soap_ilist *ip; + if (id && *id) + { ip = soap_lookup(soap, id); + if (ip) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup id='%s' type=%d\n", id, ip->type)); + return ip->type; + } + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "lookup type id='%s' NOT FOUND! Need to get it from xsi:type\n", id)); + return 0; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_id_lookup(struct soap *soap, const char *id, void **p, int t, size_t n, unsigned int k) +{ struct soap_ilist *ip; + void **q; + if (!id || !*id) + return p; + soap->alloced = 0; + if (!p) + p = (void**)soap_malloc(soap, sizeof(void*)); + ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */ + if (!ip) + { ip = soap_enter(soap, id); /* new hash table entry for string id */ + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding first href='%s' type=%d %p (%u bytes)\n", id, t, p, (unsigned int)n)); + ip->type = t; + ip->size = n; + ip->link = p; + ip->copy = NULL; + ip->flist = NULL; + ip->ptr = NULL; + ip->level = k; + *p = NULL; + } + else if (ip->ptr) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolved href='%s' type=%d location=%p (%u bytes)\n", id, t, ip->ptr, (unsigned int)n)); + if (ip->type != t) + { strcpy(soap->id, id); + soap->error = SOAP_HREF; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility: id type=%d href type=%d\n", ip->type, t)); + return NULL; + } + while (ip->level < k) + { q = (void**)soap_malloc(soap, sizeof(void*)); + if (!q) + return NULL; + *p = (void*)q; + p = q; + k--; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); + } + *p = ip->ptr; + } + else if (ip->level > k) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving level %u pointers to href='%s'\n", ip->level, id)); + while (ip->level > k) + { void *s, **r = &ip->link; + q = (void**)ip->link; + while (q) + { *r = (void*)soap_malloc(soap, sizeof(void*)); + s = *q; + *q = *r; + r = (void**)*r; + q = (void**)s; + } + *r = NULL; + ip->size = n; + ip->copy = NULL; + ip->level = ip->level - 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); + } + q = (void**)ip->link; + ip->link = p; + *p = (void*)q; + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarded href='%s' type=%d location=%p (%u bytes)\n", id, t, p, (unsigned int)n)); + while (ip->level < k) + { q = (void**)soap_malloc(soap, sizeof(void*)); + *p = q; + p = q; + k--; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); + } + q = (void**)ip->link; + ip->link = p; + *p = (void*)q; + } + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_id_forward(struct soap *soap, const char *href, void *p, int st, int tt, size_t n, unsigned int k, void (*fcopy)(struct soap*, int, int, void*, const void*, size_t)) +{ struct soap_ilist *ip; + if (!p || !href || !*href) + return p; + ip = soap_lookup(soap, href); /* lookup pointer to hash table entry for string id */ + if (!ip) + { ip = soap_enter(soap, href); /* new hash table entry for string id */ + ip->type = st; + ip->size = n; + ip->link = NULL; + ip->copy = NULL; + ip->ptr = NULL; + ip->level = 0; + ip->flist = NULL; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "New entry href='%s' type=%d size=%lu level=%d location=%p\n", href, st, (unsigned long)n, k, p)); + } + else if (ip->type != st || (ip->level == k && ip->size != n)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n", href, ip->type, (unsigned long)ip->size, k, st, (unsigned long)n)); + strcpy(soap->id, href); + soap->error = SOAP_HREF; + return NULL; + } + if (fcopy || n < sizeof(void*) || *href != '#') + { register struct soap_flist *fp = (struct soap_flist*)SOAP_MALLOC(sizeof(struct soap_flist)); + if (!fp) + { soap->error = SOAP_EOM; + return NULL; + } + fp->next = ip->flist; + fp->type = tt; + fp->ptr = p; + fp->level = k; + if (fcopy) + fp->fcopy = fcopy; + else + fp->fcopy = soap_fcopy; + ip->flist = fp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding type=%d (target type=%d) size=%lu location=%p level=%u href='%s'\n", st, tt, (unsigned long)n, p, k, href)); + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding copying address %p for type=%d href='%s'\n", p, st, href)); + *(void**)p = ip->copy; + ip->copy = p; + } + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_id_enter(struct soap *soap, const char *id, void *p, int t, size_t n, unsigned int k, const char *type, const char *arrayType, void *(*finstantiate)(struct soap*, int, const char*, const char*, size_t*)) +{ struct soap_ilist *ip; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Enter id='%s' type=%d loc=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k)); + soap->alloced = 0; + if (!p) + { if (finstantiate) + p = finstantiate(soap, t, type, arrayType, &n); + else + p = soap_malloc(soap, n); + if (p) + soap->alloced = 1; + } + if (!id || !*id) + return p; + ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */ + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Lookup entry id='%s for location=%p'\n", id, p)); + if (!ip) + { ip = soap_enter(soap, id); /* new hash table entry for string id */ + ip->type = t; + ip->link = NULL; + ip->copy = NULL; + ip->flist = NULL; + ip->size = n; + ip->ptr = p; + ip->level = k; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "New entry id='%s' type=%d size=%lu level=%u location=%p\n", id, t, (unsigned long)n, k, p)); + } + else if ((ip->type != t || (ip->level == k && ip->size != n)) && (ip->copy || ip->flist)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n", id, ip->type, (unsigned long)ip->size, k, t, (unsigned long)n)); + strcpy(soap->id, id); + soap->error = SOAP_HREF; + return NULL; + } + else if (ip->ptr) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Multiply defined id='%s'\n", id)); + strcpy(soap->id, id); + soap->error = SOAP_MULTI_ID; + return NULL; + } + else + { ip->size = n; + ip->ptr = p; + ip->level = k; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update entry id='%s' type=%d location=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k)); + } + return ip->ptr; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_fcopy(struct soap *soap, int st, int tt, void *p, const void *q, size_t n) +{ DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Copying data type=%d (target type=%d) %p -> %p (%lu bytes)\n", st, tt, q, p, (unsigned long)n)); + memcpy(p, q, n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_end_send(struct soap *soap) +{ +#ifndef WITH_LEANER + if (soap->dime.list) + { /* SOAP body referenced attachments must appear first */ + soap->dime.last->next = soap->dime.first; + soap->dime.first = soap->dime.list->next; + soap->dime.list->next = NULL; + soap->dime.last = soap->dime.list; + } + if (soap_putdime(soap) || soap_putmime(soap)) + return soap->error; + soap->mime.list = NULL; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->dime.list = NULL; + soap->dime.first = NULL; + soap->dime.last = NULL; +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End send\n")); + if (soap->mode & SOAP_IO) /* need to flush the remaining data in buffer */ + { if (soap_flush(soap)) +#ifdef WITH_ZLIB + { if (soap->mode & SOAP_ENC_ZLIB && soap->zlib_state == SOAP_ZLIB_DEFLATE) + { soap->zlib_state = SOAP_ZLIB_NONE; + deflateEnd(&soap->d_stream); + } + return soap->error; + } +#else + return soap->error; +#endif +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { int r; + soap->d_stream.avail_in = 0; + do + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating remainder\n")); + r = deflate(&soap->d_stream, Z_FINISH); + if (soap->d_stream.avail_out != SOAP_BUFLEN) + { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN - soap->d_stream.avail_out)) + { soap->zlib_state = SOAP_ZLIB_NONE; + deflateEnd(&soap->d_stream); + return soap->error; + } + soap->d_stream.next_out = (Byte*)soap->z_buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + } + } while (r == Z_OK); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out)); + soap->z_ratio_out = (float)soap->d_stream.total_out / (float)soap->d_stream.total_in; + soap->mode &= ~SOAP_ENC_ZLIB; + soap->zlib_state = SOAP_ZLIB_NONE; + if (deflateEnd(&soap->d_stream) != Z_OK || r != Z_STREAM_END) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to end deflate: %s\n", soap->d_stream.msg?soap->d_stream.msg:"")); + return soap->error = SOAP_ZLIB_ERROR; + } +#ifdef WITH_GZIP + soap->z_buf[0] = soap->z_crc & 0xFF; + soap->z_buf[1] = (soap->z_crc >> 8) & 0xFF; + soap->z_buf[2] = (soap->z_crc >> 16) & 0xFF; + soap->z_buf[3] = (soap->z_crc >> 24) & 0xFF; + soap->z_buf[4] = soap->d_stream.total_in & 0xFF; + soap->z_buf[5] = (soap->d_stream.total_in >> 8) & 0xFF; + soap->z_buf[6] = (soap->d_stream.total_in >> 16) & 0xFF; + soap->z_buf[7] = (soap->d_stream.total_in >> 24) & 0xFF; + if (soap_flush_raw(soap, soap->z_buf, 8)) + return soap->error; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip crc32=%lu\n", (unsigned long)soap->z_crc)); +#endif + } +#endif + if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) + { char *p; + if (!(soap->mode & SOAP_ENC_XML)) + { soap->mode--; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending buffered message of length %u\n", (unsigned int)soap->blist->size)); + if (soap->status >= SOAP_POST) + soap->error = soap->fpost(soap, soap->endpoint, soap->host, soap->port, soap->path, soap->action, soap->blist->size); + else if (soap->status != SOAP_STOP) + soap->error = soap->fresponse(soap, soap->status, soap->blist->size); + if (soap->error || soap_flush(soap)) + return soap->error; + soap->mode++; + } + for (p = soap_first_block(soap); p; p = soap_next_block(soap)) + { DBGMSG(SENT, p, soap_block_size(soap)); + if ((soap->error = soap->fsend(soap, p, soap_block_size(soap)))) + { soap_end_block(soap); + return soap->error; + } + } + soap_end_block(soap); + } + else if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) + { DBGMSG(SENT, "\r\n0\r\n\r\n", 7); + if ((soap->error = soap->fsend(soap, "\r\n0\r\n\r\n", 7))) + return soap->error; + } + } +#ifdef WITH_OPENSSL + if (!soap->ssl && soap_valid_socket(soap->socket) && !soap->keep_alive) + soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 1); /* Send TCP FIN */ +#else + if (soap_valid_socket(soap->socket) && !soap->keep_alive) + soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 1); /* Send TCP FIN */ +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of send message ok\n")); + soap->part = SOAP_END; + soap->count = 0; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_end_recv(struct soap *soap) +{ soap->part = SOAP_END; +#ifndef WITH_LEANER + if ((soap->mode & SOAP_ENC_MIME) && soap_getmime(soap)) + return soap->error; + soap->mime.list = soap->mime.first; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->dime.list = soap->dime.first; + soap->dime.first = NULL; + soap->dime.last = NULL; +#endif + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "End of receive message ok\n")); +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { soap->mode &= ~SOAP_ENC_ZLIB; + memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN); + soap->bufidx = (char*)soap->d_stream.next_in - soap->z_buf; + soap->buflen = soap->z_buflen; + soap->zlib_state = SOAP_ZLIB_NONE; + if (inflateEnd(&soap->d_stream) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; +#ifdef WITH_GZIP + if (soap->zlib_in == SOAP_ZLIB_GZIP) + { soap_wchar c; + short i; + for (i = 0; i < 8; i++) + { if ((int)(c = soap_getchar(soap)) == EOF) + return soap->error = SOAP_EOF; + soap->z_buf[i] = (char)c; + } + if (soap->z_crc != ((uLong)(unsigned char)soap->z_buf[0] | ((uLong)(unsigned char)soap->z_buf[1] << 8) | ((uLong)(unsigned char)soap->z_buf[2] << 16) | ((uLong)(unsigned char)soap->z_buf[3] << 24))) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: crc check failed, message corrupted? (crc32=%lu)\n", (unsigned long)soap->z_crc)); + return soap->error = SOAP_ZLIB_ERROR; + } + if (soap->d_stream.total_out != ((uLong)(unsigned char)soap->z_buf[4] | ((uLong)(unsigned char)soap->z_buf[5] << 8) | ((uLong)(unsigned char)soap->z_buf[6] << 16) | ((uLong)(unsigned char)soap->z_buf[7] << 24))) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: incorrect message length\n")); + return soap->error = SOAP_ZLIB_ERROR; + } + } +#endif + } +#endif + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) + while ((int)soap_getchar(soap) != EOF) /* advance to last chunk */ + ; + if (soap->fdisconnect && (soap->error = soap->fdisconnect(soap))) + return soap->error; + return soap_resolve(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_free(struct soap *soap) +{ register struct soap_nlist *np; + register struct soap_attribute *tp; + register struct Namespace *ns; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free namespace stack\n")); + while (soap->nlist) + { np = soap->nlist->next; + if (soap->nlist->ns) + SOAP_FREE(soap->nlist->ns); + SOAP_FREE(soap->nlist); + soap->nlist = np; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free any remaining temp blocks\n")); + while (soap->blist) + soap_end_block(soap); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attributes\n")); + while (soap->attributes) + { tp = soap->attributes->next; + if (soap->attributes->value) + SOAP_FREE(soap->attributes->value); + SOAP_FREE(soap->attributes); + soap->attributes = tp; + } +#ifdef WITH_FAST + if (soap->labbuf) + SOAP_FREE(soap->labbuf); + soap->labbuf = NULL; + soap->lablen = 0; + soap->labidx = 0; +#endif + soap_free_pht(soap); + soap_free_iht(soap); + ns = soap->local_namespaces; + if (ns) + { for (; ns->id; ns++) + { if (ns->out) + { SOAP_FREE(ns->out); + if (soap->encodingStyle == ns->out) + soap->encodingStyle = SOAP_STR_EOS; + ns->out = NULL; + } + if (soap->encodingStyle == ns->ns) + soap->encodingStyle = SOAP_STR_EOS; + } + SOAP_FREE(soap->local_namespaces); + soap->local_namespaces = NULL; + } +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +static void +soap_init_logs(struct soap *soap) +{ int i; + for (i = 0; i < SOAP_MAXLOGS; i++) + { soap->logfile[i] = NULL; + soap->fdebug[i] = NULL; + } +} +#endif + +/******************************************************************************/ +#if !defined(WITH_LEAN) || defined(SOAP_DEBUG) +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_open_logfile(struct soap *soap, int i) +{ if (soap->logfile[i]) + soap->fdebug[i] = fopen(soap->logfile[i], i < 2 ? "ab" : "a"); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +static void +soap_close_logfile(struct soap *soap, int i) +{ if (soap->fdebug[i]) + { fclose(soap->fdebug[i]); + soap->fdebug[i] = NULL; + } +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_close_logfiles(struct soap *soap) +{ int i; + for (i = 0; i < SOAP_MAXLOGS; i++) + soap_close_logfile(soap, i); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +static void +soap_set_logfile(struct soap *soap, int i, const char *logfile) +{ char *s = NULL; + soap_close_logfile(soap, i); + if (soap->logfile[i]) + SOAP_FREE((void*)soap->logfile[i]); + if (logfile) + if ((s = (char*)SOAP_MALLOC(strlen(logfile) + 1))) + strcpy(s, logfile); + soap->logfile[i] = s; +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_recv_logfile(struct soap *soap, const char *logfile) +{ soap_set_logfile(soap, SOAP_INDEX_RECV, logfile); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_sent_logfile(struct soap *soap, const char *logfile) +{ soap_set_logfile(soap, SOAP_INDEX_SENT, logfile); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_test_logfile(struct soap *soap, const char *logfile) +{ soap_set_logfile(soap, SOAP_INDEX_TEST, logfile); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_copy(struct soap *soap) +{ return soap_copy_context((struct soap*)SOAP_MALLOC(sizeof(struct soap)), soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_copy_context(struct soap *copy, struct soap *soap) +{ if (copy) + { register struct soap_plugin *p; + memcpy(copy, soap, sizeof(struct soap)); + copy->copy = 1; + copy->user = NULL; + copy->userid = NULL; + copy->passwd = NULL; + copy->nlist = NULL; + copy->blist = NULL; + copy->clist = NULL; + copy->alist = NULL; + copy->attributes = NULL; + copy->local_namespaces = NULL; + soap_set_local_namespaces(copy); + soap_init_iht(copy); + soap_init_pht(copy); + copy->header = NULL; + copy->fault = NULL; + copy->action = NULL; + *copy->host = '\0'; +#ifndef WITH_LEAN +#ifdef WITH_COOKIES + copy->cookies = soap_copy_cookies(soap); +#else + copy->cookies = NULL; +#endif +#endif +#ifdef SOAP_DEBUG + soap_init_logs(copy); + soap_set_recv_logfile(copy, "RECV.log"); + soap_set_sent_logfile(copy, "SENT.log"); + soap_set_test_logfile(copy, "TEST.log"); +#endif + copy->plugins = NULL; + for (p = soap->plugins; p; p = p->next) + { register struct soap_plugin *q = (struct soap_plugin*)SOAP_MALLOC(sizeof(struct soap_plugin)); + if (!q) + return NULL; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying plugin '%s'\n", p->id)); + *q = *p; + if (p->fcopy && (soap->error = p->fcopy(soap, q, p))) + { SOAP_FREE(q); + return NULL; + } + q->next = copy->plugins; + copy->plugins = q; + } + } + else + soap->error = SOAP_EOM; + return copy; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_init(struct soap *soap) +{ soap->version = 0; + soap_imode(soap, SOAP_IO_DEFAULT); + soap_omode(soap, SOAP_IO_DEFAULT); + soap->copy = 0; + soap->plugins = NULL; + soap->user = NULL; + soap->userid = NULL; + soap->passwd = NULL; + soap->fpost = http_post; + soap->fget = http_get; + soap->fposthdr = http_post_header; + soap->fresponse = http_response; + soap->fparse = http_parse; + soap->fparsehdr = http_parse_header; + soap->fconnect = NULL; + soap->fdisconnect = NULL; +#ifndef MAC_CARBON +#ifndef WITH_IPV6 + soap->fresolve = tcp_gethost; +#else + soap->fresolve = NULL; +#endif + soap->faccept = tcp_accept; + soap->fopen = tcp_connect; + soap->fclose = tcp_disconnect; + soap->fclosesocket = tcp_closesocket; + soap->fshutdownsocket = tcp_shutdownsocket; + soap->fsend = fsend; + soap->frecv = frecv; + soap->fpoll = soap_poll; +#else + soap->fpoll = NULL; +#endif + soap->fprepareinit = NULL; + soap->fpreparesend = NULL; + soap->fpreparerecv = NULL; + soap->fignore = NULL; + soap->fserveloop = NULL; + soap->fplugin = fplugin; + soap->fdimereadopen = NULL; + soap->fdimewriteopen = NULL; + soap->fdimereadclose = NULL; + soap->fdimewriteclose = NULL; + soap->fdimeread = NULL; + soap->fdimewrite = NULL; + soap->float_format = "%.8g"; /* .8 preserves single FP precision as much as possible, but might not be very efficient */ + soap->double_format = "%.17lg"; /* .17 preserves double FP precision as much as possible, but might not be very efficient */ + soap->dime_id_format = "cid:id%d"; /* default DIME id format */ + soap->http_version = "1.1"; + soap->actor = NULL; + soap->max_keep_alive = SOAP_MAXKEEPALIVE; + soap->keep_alive = 0; + soap->recv_timeout = 0; + soap->send_timeout = 0; + soap->connect_timeout = 0; + soap->accept_timeout = 0; + soap->socket_flags = 0; + soap->connect_flags = 0; + soap->bind_flags = 0; + soap->accept_flags = 0; + soap->ip = 0; + soap->labbuf = NULL; + soap->lablen = 0; + soap->labidx = 0; + soap->encodingStyle = SOAP_STR_EOS; +#ifndef WITH_NONAMESPACES + soap->namespaces = namespaces; +#else + soap->namespaces = NULL; +#endif + soap->local_namespaces = NULL; + soap->nlist = NULL; + soap->blist = NULL; + soap->clist = NULL; + soap->alist = NULL; + soap->attributes = NULL; + soap->header = NULL; + soap->fault = NULL; + soap->master = SOAP_INVALID_SOCKET; + soap->socket = SOAP_INVALID_SOCKET; + soap->os = NULL; + soap->is = NULL; + soap->dom = NULL; + soap->dime.list = NULL; + soap->dime.first = NULL; + soap->dime.last = NULL; + soap->mime.list = NULL; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = NULL; + soap->mime.start = NULL; +#ifndef UNDER_CE + soap->recvfd = 0; + soap->sendfd = 1; +#else + soap->recvfd = stdin; + soap->sendfd = stdout; +#endif + soap->host[0] = '\0'; + soap->port = 0; + soap->action = NULL; + soap->proxy_host = NULL; + soap->proxy_port = 8080; + soap->proxy_userid = NULL; + soap->proxy_passwd = NULL; + soap->authrealm = NULL; + soap->prolog = NULL; +#ifdef WITH_OPENSSL + soap->fsslauth = ssl_auth_init; + soap->fsslverify = ssl_verify_callback; + soap->bio = NULL; + soap->ssl = NULL; + soap->ctx = NULL; + soap->require_server_auth = 0; + soap->require_client_auth = 0; + soap->rsa = 0; + soap->keyfile = NULL; + soap->password = NULL; + soap->dhfile = NULL; + soap->cafile = NULL; + soap->capath = NULL; + soap->randfile = NULL; + soap->session = NULL; +#endif +#ifdef WITH_ZLIB + soap->zlib_state = SOAP_ZLIB_NONE; + soap->zlib_in = SOAP_ZLIB_NONE; + soap->zlib_out = SOAP_ZLIB_NONE; + soap->d_stream.zalloc = NULL; + soap->d_stream.zfree = NULL; + soap->d_stream.opaque = NULL; + soap->z_level = 6; +#endif +#ifndef WITH_LEAN + soap->cookies = NULL; + soap->cookie_domain = NULL; + soap->cookie_path = NULL; + soap->cookie_max = 32; +#endif +#ifdef SOAP_DEBUG + soap_init_logs(soap); + soap_set_recv_logfile(soap, "RECV.log"); + soap_set_sent_logfile(soap, "SENT.log"); + soap_set_test_logfile(soap, NULL); +#endif +/* WR[ */ +#ifdef WMW_RPM_IO + soap->rpmreqid = NULL; +#endif /* WMW_RPM_IO */ +/* ]WR */ +#ifdef PALM + palmNetLibOpen(); +#endif + soap_init_iht(soap); + soap_init_pht(soap); + soap_begin(soap); +#ifdef SOAP_DEBUG + soap_set_test_logfile(soap, "TEST.log"); +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_init1(struct soap *soap, int mode) +{ soap_init2(soap, mode, mode); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_init2(struct soap *soap, int imode, int omode) +{ soap_init(soap); + soap_imode(soap, imode); + soap_omode(soap, omode); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_begin(struct soap *soap) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing\n")); + if (!soap->keep_alive) + { soap->buflen = 0; + soap->bufidx = 0; + } + soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0); + soap->null = 0; + soap->position = 0; + soap->encoding = 0; + soap->mustUnderstand = 0; + soap->mode = 0; + soap->ns = 0; + soap->part = SOAP_BEGIN; + soap->alloced = 0; + soap->count = 0; + soap->length = 0; + soap->cdata = 0; + soap->error = SOAP_OK; + soap->peeked = 0; + soap->ahead = 0; + soap->idnum = 0; + soap->level = 0; + soap->endpoint[0] = '\0'; + soap->dime.chunksize = 0; + soap->dime.buflen = 0; + soap_free(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_end(struct soap *soap) +{ register struct soap_clist *cp; + soap_free(soap); + soap_dealloc(soap, NULL); + while (soap->clist) + { cp = soap->clist->next; + SOAP_FREE(soap->clist); + soap->clist = cp; + } + soap_closesock(soap); +#ifdef SOAP_DEBUG + soap_close_logfiles(soap); +#endif +#ifdef PALM + palmNetLibClose(); +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_namespaces(struct soap *soap, struct Namespace *p) +{ struct Namespace *ns = soap->local_namespaces; + struct soap_nlist *np, *nq, *nr; + unsigned int level = soap->level; + soap->namespaces = p; + soap->local_namespaces = NULL; + soap_set_local_namespaces(soap); + /* reverse the list */ + np = soap->nlist; + soap->nlist = NULL; + if (np) + { nq = np->next; + np->next = NULL; + while (nq) + { nr = nq->next; + nq->next = np; + np = nq; + nq = nr; + } + } + while (np) + { soap->level = np->level; /* preserve element nesting level */ + if (np->ns) + { if (soap_push_namespace(soap, np->id, np->ns)) + return soap->error; + } + else if (np->index >= 0 && ns) + { if (ns[np->index].out) + { if (soap_push_namespace(soap, np->id, ns[np->index].out)) + return soap->error; + } + else if (soap_push_namespace(soap, np->id, ns[np->index].ns)) + return soap->error; + } + if (np->ns) + SOAP_FREE(np->ns); + nq = np; + np = np->next; + SOAP_FREE(nq); + } + if (ns) + { int i; + for (i = 0; ns[i].id; i++) + { if (ns[i].out) + { SOAP_FREE(ns[i].out); + ns[i].out = NULL; + } + } + SOAP_FREE(ns); + } + soap->level = level; /* restore level */ + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static void +soap_set_local_namespaces(struct soap *soap) +{ if (soap->namespaces && !soap->local_namespaces) + { register const struct Namespace *ns1; + register struct Namespace *ns2; + register size_t n = 1; + for (ns1 = soap->namespaces; ns1->id; ns1++) + n++; + if (n > 3) + { n *= sizeof(struct Namespace); + ns2 = (struct Namespace*)SOAP_MALLOC(n); + if (ns2) + { memcpy(ns2, soap->namespaces, n); + ns2[0].id = "SOAP-ENV"; + ns2[1].id = "SOAP-ENC"; + ns2[2].id = "xsi"; + if (ns2[0].ns) + { if (!strcmp(ns2[0].ns, soap_env1)) + soap->version = 1; + else + soap->version = 2; + } + soap->local_namespaces = ns2; + } + } + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element(struct soap *soap, const char *tag, int id, const char *type) +{ struct Namespace *ns = soap->local_namespaces; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element begin tag='%s' id='%d' type='%s'\n", tag, id, type?type:"")); +/**/ +#ifdef WITH_DOM + if (soap->mode & SOAP_XML_DOM) + { register struct soap_dom_element *p, *e = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element)); + e->next = NULL; + e->prnt = soap->dom; + e->nstr = NULL; + e->name = soap_strdup(soap, tag); /* check EOM? */ + e->data = NULL; + e->type = 0; + e->node = NULL; + e->elts = NULL; + e->atts = NULL; + if (soap->dom) + { p = soap->dom->elts; + if (p) + { while (p->next) + p = p->next; + p->next = e; + } + else + soap->dom->elts = e; + } + soap->dom = e; + } + else +#endif +{ + soap->level++; + if (!soap->ns && !(soap->mode & SOAP_XML_CANONICAL)) + if (soap_send(soap, soap->prolog ? soap->prolog : "")) + return soap->error; + if (soap_send_raw(soap, "<", 1) + || soap_send(soap, tag)) + return soap->error; +} +/**/ + if (!soap->ns) + { for (ns = soap->local_namespaces; ns && ns->id; ns++) + { if (*ns->id && (ns->out || ns->ns)) + { sprintf(soap->tmpbuf, "xmlns:%s", ns->id); + if (soap_attribute(soap, soap->tmpbuf, ns->out ? ns->out : ns->ns)) + return soap->error; + } + } + soap->ns = 1; + } + if (id > 0) + { sprintf(soap->tmpbuf, "_%d", id); + if (soap_attribute(soap, "id", soap->tmpbuf)) + return soap->error; + } + if (type && *type) + { if (soap_attribute(soap, "xsi:type", type)) + return soap->error; + } + if (soap->null && soap->position > 0) + { int i; + sprintf(soap->tmpbuf, "[%d", soap->positions[0]); + for (i = 1; i < soap->position; i++) + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), ",%d", soap->positions[i]); + strcat(soap->tmpbuf, "]"); + if (soap_attribute(soap, "SOAP-ENC:position", soap->tmpbuf)) + return soap->error; + } + if (soap->mustUnderstand) + { if (soap->actor && *soap->actor) + { if (soap_attribute(soap, soap->version == 2 ? "SOAP-ENV:role" : "SOAP-ENV:actor", soap->actor)) + return soap->error; + } + if (soap_attribute(soap, "SOAP-ENV:mustUnderstand", soap->version == 2 ? "true" : "1")) + return soap->error; + soap->mustUnderstand = 0; + } + if (soap->encoding) + { if (soap->encodingStyle && soap->local_namespaces) + { if (!*soap->encodingStyle) + { if (soap->local_namespaces[1].out) + soap->encodingStyle = soap->local_namespaces[1].out; + else + soap->encodingStyle = soap->local_namespaces[1].ns; + } + if (soap_attribute(soap, "SOAP-ENV:encodingStyle", soap->encodingStyle)) + return soap->error; + } + soap->encoding = 0; + } + soap->null = 0; + soap->position = 0; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_begin_out(struct soap *soap, const char *tag, int id, const char *type) +{ if (*tag == '-') + return SOAP_OK; + if (soap_element(soap, tag, id, type)) + return soap->error; + return soap_element_start_end_out(soap, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +#ifndef HAVE_STRRCHR +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_strrchr(const char *s, int t) +{ register char *r = NULL; + while (*s) + if (*s++ == t) + r = (char*)s - 1; + return r; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +#ifndef HAVE_STRTOL +SOAP_FMAC1 +long +SOAP_FMAC2 +soap_strtol(const char *s, char **t, int b) +{ register long n = 0; + register int c; + while (*s > 0 && *s <= 32) + s++; + if (b == 10) + { short neg = 0; + if (*s == '-') + { s++; + neg = 1; + } + else if (*s == '+') + s++; + while ((c = *s) && c >= '0' && c <= '9') + { if (n > 214748364) + break; + n *= 10; + n += c - '0'; + s++; + } + if (neg) + n = -n; + } + else /* b == 16 and value is always positive */ + { while ((c = *s)) + { if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'F') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'f') + c -= 'a' - 10; + if (n > 0x07FFFFFF) + break; + n <<= 4; + n += c; + s++; + } + } + if (t) + *t = (char*)s; + return n; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +#ifndef HAVE_STRTOUL +SOAP_FMAC1 +unsigned long +SOAP_FMAC2 +soap_strtoul(const char *s, char **t, int b) +{ unsigned long n = 0; + register int c; + while (*s > 0 && *s <= 32) + s++; + if (b == 10) + { if (*s == '+') + s++; + while ((c = *s) && c >= '0' && c <= '9') + { if (n > 429496729) + break; + n *= 10; + n += c - '0'; + s++; + } + } + else /* b == 16 */ + { while ((c = *s)) + { if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'F') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'f') + c -= 'a' - 10; + if (n > 0x0FFFFFFF) + break; + n <<= 4; + n += c; + s++; + } + } + if (t) + *t = (char*)s; + return n; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_array_begin_out(struct soap *soap, const char *tag, int id, const char *type, const char *offset) +{ if (soap_element(soap, tag, id, "SOAP-ENC:Array")) + return soap->error; + if (soap->version == 2) + { const char *s; + s = soap_strrchr(type, '['); + if ((size_t)(s - type) < sizeof(soap->tmpbuf)) + { strncpy(soap->tmpbuf, type, s - type); + soap->tmpbuf[s - type] = '\0'; + if (type && *type && (soap_attribute(soap, "SOAP-ENC:itemType", soap->tmpbuf))) + return soap->error; + if (s && (soap_attribute(soap, "SOAP-ENC:arraySize", s + 1))) + return soap->error; + } + } + else + { if (offset && (soap_attribute(soap, "SOAP-ENC:offset", offset))) + return soap->error; + if (type && *type && (soap_attribute(soap, "SOAP-ENC:arrayType", type))) + return soap->error; + } + return soap_element_start_end_out(soap, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_start_end_out(struct soap *soap, const char *tag) +{ register struct soap_attribute *tp; +/**/ +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible) + { register struct soap_dom_attribute *a = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); + a->next = soap->dom->atts; + a->nstr = NULL; + a->name = soap_strdup(soap, tp->name); /* check EOM */ + a->data = soap_strdup(soap, tp->value); /* check EOM */ + a->wide = NULL; + soap->dom->atts = a; + tp->visible = 0; + } + } + return SOAP_OK; + } +#endif +/**/ + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible) + { if (soap_send2(soap, " ", tp->name)) + return soap->error; + if (tp->visible == 2 && tp->value) + if (soap_send_raw(soap, "=\"", 2) + || soap_string_out(soap, tp->value, 1) + || soap_send_raw(soap, "\"", 1)) + return soap->error; + tp->visible = 0; + } + } + if (tag) + { soap->level--; +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { if (soap_send_raw(soap, ">", 1) + || soap_element_end_out(soap, tag)) + return soap->error; + return SOAP_OK; + } +#endif + return soap_send_raw(soap, "/>", 2); + } + return soap_send_raw(soap, ">", 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_end_out(struct soap *soap, const char *tag) +{ if (*tag == '-') + return SOAP_OK; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element ending tag='%s'\n", tag)); +/**/ +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { if (soap->dom->prnt) + soap->dom = soap->dom->prnt; + return SOAP_OK; + } +#endif +/**/ + soap->level--; + if (soap_send_raw(soap, "error; + return soap_send_raw(soap, ">", 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_ref(struct soap *soap, const char *tag, int id, int href) +{ register int n = 0; + if (soap->version == 2) + n = 1; + sprintf(soap->href, "#_%d", href); + return soap_element_href(soap, tag, id, "href" + n, soap->href + n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_href(struct soap *soap, const char *tag, int id, const char *ref, const char *val) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element '%s' reference %s='%s'\n", tag, ref, val)); + if (soap_element(soap, tag, id, NULL) + || soap_attribute(soap, ref, val) + || soap_element_start_end_out(soap, tag)) + return soap->error; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_null(struct soap *soap, const char *tag, int id, const char *type) +{ struct soap_attribute *tp; + for (tp = soap->attributes; tp; tp = tp->next) + if (tp->visible) + break; + if (tp || (soap->version == 2 && soap->position > 0) || id > 0 || (soap->mode & SOAP_XML_NIL)) + { if (soap_element(soap, tag, id, type)) + return soap->error; + if (soap->part != SOAP_IN_HEADER && soap->encodingStyle) + if (soap_attribute(soap, "xsi:nil", "true")) + return soap->error; + return soap_element_start_end_out(soap, tag); + } + soap->null = 1; + soap->position = 0; + soap->mustUnderstand = 0; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_id(struct soap *soap, const char *tag, int id, const void *p, const struct soap_array *a, int n, const char *type, int t) +{ struct soap_plist *pp; + if (!p || (a && !a->__ptr)) + { soap_element_null(soap, tag, id, type); + return -1; + } + if (soap->mode & SOAP_XML_TREE) + return 0; + if (id < 0) + { if (a) + id = soap_array_pointer_lookup(soap, p, a, n, t, &pp); + else + id = soap_pointer_lookup(soap, p, t, &pp); + if (id) + { if (soap_is_embedded(soap, pp)) + { soap_element_ref(soap, tag, 0, id); + return -1; + } + if (soap_is_single(soap, pp)) + return 0; + soap_set_embedded(soap, pp); + } + } + return id; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_result(struct soap *soap, const char *tag) +{ if (soap->version == 2 && soap->encodingStyle) + if (soap_element(soap, "SOAP-RPC:result", 0, NULL) + || soap_attribute(soap, "xmlns:SOAP-RPC", soap_rpc) + || soap_element_start_end_out(soap, NULL) + || soap_string_out(soap, tag, 0) + || soap_element_end_out(soap, "SOAP-RPC:result")) + return soap->error; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_attribute(struct soap *soap, const char *name, const char *value) +{ +/**/ +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { register struct soap_dom_attribute *a = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); + a->next = soap->dom->atts; + a->nstr = NULL; + a->name = soap_strdup(soap, name); /* check EOM */ + a->data = soap_strdup(soap, value); /* check EOM */ + a->wide = NULL; + soap->dom->atts = a; + return SOAP_OK; + } +#endif +/**/ +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { if (soap_set_attr(soap, name, value)) + return soap->error; + } + else +#endif + { if (soap_send2(soap, " ", name)) + return soap->error; + if (value) + if (soap_send_raw(soap, "=\"", 2) + || soap_string_out(soap, value, 1) + || soap_send_raw(soap, "\"", 1)) + return soap->error; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_begin_in(struct soap *soap, const char *tag, int nillable) +{ if (!soap_peek_element(soap)) + { if (soap->other) + return soap->error = SOAP_TAG_MISMATCH; + if (tag && *tag == '-') + return SOAP_OK; + if (!(soap->error = soap_match_tag(soap, soap->tag, tag))) + { soap->peeked = 0; + if (soap->body) + soap->level++; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:"" )); + if (!nillable && soap->null && (soap->mode & SOAP_XML_STRICT)) + return soap->error = SOAP_NULL; + } + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_end_in(struct soap *soap, const char *tag) +{ register soap_wchar c; + register char *s; + register const char *t; + if (tag && *tag == '-') + return SOAP_OK; + soap->level--; + soap_pop_namespace(soap); + if (soap->peeked) + { if (*soap->tag == '\0') + { soap->peeked = 0; + if (soap->error == SOAP_NO_TAG || soap->error == SOAP_TAG_END) + soap->error = SOAP_OK; + } + else + return soap->error = SOAP_TAG_END; + } + else + { while (((c = soap_get(soap)) != SOAP_TT)) + { if ((int)c == EOF) + return soap->error = SOAP_EOF; + if (c == SOAP_LT) + return soap->error = SOAP_TAG_END; + } + } + s = soap->tag; + do c = soap_get(soap); + while (soap_blank(c)); + do + { *s++ = (char)c; + c = soap_get(soap); + } while (soap_notblank(c)); + *s = '\0'; + if ((int)c == EOF) + return soap->error = SOAP_EOF; + while (soap_blank(c)) + c = soap_get(soap); + if (c != SOAP_GT) + return soap->error = SOAP_SYNTAX_ERROR; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:"")); + if (!tag) + return SOAP_OK; + if ((s = strchr(soap->tag, ':'))) + s++; + else + s = soap->tag; + if ((t = strchr(tag, ':'))) + t++; + else + t = tag; + if (!SOAP_STRCMP(s, t)) + return SOAP_OK; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element tag name does not match\n")); + return soap->error = SOAP_SYNTAX_ERROR; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char * +SOAP_FMAC2 +soap_attr_value(struct soap *soap, const char *name, int flag) +{ register struct soap_attribute *tp; + for (tp = soap->attributes; tp; tp = tp->next) + if (!soap_match_tag(soap, tp->name, name)) + break; + if (tp && tp->visible == 2) + { if (flag == 2 && (soap->mode & SOAP_XML_STRICT)) + soap->error = SOAP_PROHIBITED; + else + return tp->value; + } + else if (flag == 1 && (soap->mode & SOAP_XML_STRICT)) + soap->error = SOAP_REQUIRED; + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_attr(struct soap *soap, const char *name, const char *value) +{ register struct soap_attribute *tp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set attribute %s='%s'\n", name, value?value:"")); + for (tp = soap->attributes; tp; tp = tp->next) + if (!strcmp(tp->name, name)) + break; + if (!tp) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute %s\n", name)); + if (!(tp = (struct soap_attribute*)SOAP_MALLOC(sizeof(struct soap_attribute) + strlen(name)))) + return soap->error = SOAP_EOM; + tp->ns = NULL; +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { struct soap_attribute **tpp = &soap->attributes; + const char *s = strchr(name, ':'); + if (!strncmp(name, "xmlns", 5)) + { for (; *tpp; tpp = &(*tpp)->next) + if (strncmp((*tpp)->name, "xmlns", 5) || strcmp((*tpp)->name + 5, name + 5) > 0) + break; + } + else if (!s) + { for (; *tpp; tpp = &(*tpp)->next) + if (strncmp((*tpp)->name, "xmlns", 5) && ((*tpp)->ns || strcmp((*tpp)->name, name) > 0)) + break; + } + else + { int k; + for (; *tpp; tpp = &(*tpp)->next) + { if (!strncmp((*tpp)->name, "xmlns:", 6) && !strncmp((*tpp)->name + 6, name, s - name) && !(*tpp)->name[6 + s - name]) + { if (!tp->ns) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Canonicalization: prefix %s=%p(%s)\n", name, (*tpp)->ns, (*tpp)->ns)); + tp->ns = (*tpp)->ns; + } + } + else if (strncmp((*tpp)->name, "xmlns", 5) && (*tpp)->ns && tp->ns && ((k = strcmp((*tpp)->ns, tp->ns)) > 0 || (!k && strcmp((*tpp)->name, name) > 0))) + break; + } + } + tp->next = *tpp; + *tpp = tp; + } + else +#endif + { tp->next = soap->attributes; + soap->attributes = tp; + } + strcpy(tp->name, name); + tp->value = NULL; + } + else if (value && tp->value && tp->size <= strlen(value)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute value of %s (free %p)\n", name, tp->value)); + SOAP_FREE(tp->value); + tp->value = NULL; + tp->ns = NULL; + } + if (value) + { if (!tp->value) + { tp->size = strlen(value) + 1; + if (!(tp->value = (char*)SOAP_MALLOC(tp->size))) + return soap->error = SOAP_EOM; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute value of %s (%p)\n", tp->name, tp->value)); + } + strcpy(tp->value, value); + if (!strncmp(tp->name, "xmlns:", 6)) + tp->ns = tp->value; + tp->visible = 2; + } + else + tp->visible = 1; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_clr_attr(struct soap *soap) +{ register struct soap_attribute *tp; +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { while (soap->attributes) + { tp = soap->attributes->next; + SOAP_FREE(soap->attributes->value); + SOAP_FREE(soap->attributes); + soap->attributes = tp; + } + } + else +#endif + { for (tp = soap->attributes; tp; tp = tp->next) + tp->visible = 0; + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +static int +soap_getattrval(struct soap *soap, char *s, size_t n, soap_wchar d) +{ size_t i; + soap_wchar c; + for (i = 0; i < n; i++) + { c = soap_getutf8(soap); + switch (c) + { + case SOAP_TT: + *s++ = '<'; + soap_unget(soap, '/'); + break; + case SOAP_LT: + *s++ = '<'; + break; + case SOAP_GT: + if (d == ' ') + { soap_unget(soap, c); + *s = '\0'; + return SOAP_OK; + } + *s++ = '>'; + break; + case SOAP_QT: + if (c == d) + { *s = '\0'; + return SOAP_OK; + } + *s++ = '"'; + break; + case SOAP_AP: + if (c == d) + { *s = '\0'; + return SOAP_OK; + } + *s++ = '\''; + break; + case '\t': + case '\n': + case '\r': + case ' ': + case '/': + if (d == ' ') + { soap_unget(soap, c); + *s = '\0'; + return SOAP_OK; + } + default: + if ((int)c == EOF) + return soap->error = SOAP_EOF; + *s++ = (char)c; + } + } + return soap->error = SOAP_EOM; +} +#endif + +/******************************************************************************/ +#ifdef WITH_FAST +#ifndef PALM_2 +static int +soap_append_lab(struct soap *soap, const char *s, size_t n) +{ if (soap->labidx + n >= soap->lablen) + { register char *t = soap->labbuf; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enlarging look-aside buffer to append data, old size=%lu", (unsigned long)soap->lablen)); + if (soap->lablen == 0) + soap->lablen = SOAP_LABLEN; + while (soap->labidx + n >= soap->lablen) + soap->lablen <<= 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, ", new size=%lu\n", (unsigned long)soap->lablen)); + soap->labbuf = (char*)SOAP_MALLOC(soap->lablen); + if (!soap->labbuf) + { if (t) + free(t); + return soap->error = SOAP_EOM; + } + if (t && soap->labidx) + { memcpy(soap->labbuf, t, soap->labidx); + free(t); + } + } + if (s) + { memcpy(soap->labbuf + soap->labidx, s, n); + soap->labidx += n; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_peek_element(struct soap *soap) +{ register struct soap_attribute *tp; + const char *t; + register char *s; + register soap_wchar c; + register int i; + if (soap->error == SOAP_NO_TAG || soap->error == SOAP_TAG_END || soap->error == SOAP_TAG_MISMATCH) + soap->error = SOAP_OK; /* retry */ + if (soap->peeked) + { if (*soap->tag == '\0') + return soap->error = SOAP_NO_TAG; + return SOAP_OK; + } + soap->peeked = 1; + for (;;) + { while (((c = soap_getutf8(soap)) != SOAP_LT) && c != SOAP_TT) + { if ((int)c == EOF) + return soap->error = SOAP_EOF; + } + if (c == SOAP_TT) + { *soap->tag = '\0'; + return soap->error = SOAP_NO_TAG; /* ending tag found */ + } + s = soap->tag; + do c = soap_get(soap); + while (soap_blank(c)); + i = sizeof(soap->tag); + while (c != '/' && soap_notblank(c)) + { if (--i > 0) + *s++ = (char)c; + c = soap_get(soap); + } + while (soap_blank(c)) + c = soap_get(soap); + *s = '\0'; + if (*soap->tag != '?') + break; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "XML PI <%s?>\n", soap->tag)); + while ((int)c != EOF && c != SOAP_GT && c != '?') + { s = soap->tmpbuf; + i = sizeof(soap->tmpbuf) - 2; + while (c != '=' && c != SOAP_GT && c != '?' && soap_notblank(c)) + { if (--i > 0) + *s++ = (char)c; + c = soap_get(soap); + } + while (soap_blank(c)) + c = soap_get(soap); + if (c == '=') + { *s++ = '='; + do c = soap_get(soap); + while (soap_blank(c)); + if (c != SOAP_QT && c != SOAP_AP) + { soap_unget(soap, c); + c = ' '; /* blank delimiter */ + } + if (soap_getattrval(soap, s, i, c) == SOAP_EOM) + while (soap_getattrval(soap, soap->tmpbuf, sizeof(soap->tmpbuf), c) == SOAP_EOM) + ; + else if (!strcmp(soap->tag, "?xml") && (!soap_tag_cmp(soap->tmpbuf, "encoding=iso-8859-1") || !soap_tag_cmp(soap->tmpbuf, "encoding=latin1"))) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "XML latin1 encoding\n")); + soap->mode |= SOAP_ENC_LATIN; + } + } + do c = soap_get(soap); + while (soap_blank(c)); + } + } + soap->id[0] = '\0'; + soap->href[0] = '\0'; + soap->type[0] = '\0'; + soap->arrayType[0] = '\0'; + soap->arraySize[0] = '\0'; + soap->arrayOffset[0] = '\0'; + soap->other = 0; + soap->root = -1; + soap->position = 0; + soap->null = 0; + soap->mustUnderstand = 0; + soap_clr_attr(soap); + while ((int)c != EOF && c != SOAP_GT && c != '/') + { s = soap->tmpbuf; + i = sizeof(soap->tmpbuf); + while (c != '=' && c != '/' && soap_notblank(c)) + { if (--i > 0) + *s++ = (char)c; + c = soap_get(soap); + } + *s = '\0'; + if (i == sizeof(soap->tmpbuf)) + return soap->error = SOAP_SYNTAX_ERROR; + if (!strncmp(soap->tmpbuf, "xmlns:", 6)) + { soap->tmpbuf[5] = '\0'; + t = soap->tmpbuf + 6; + } + else if (!strcmp(soap->tmpbuf, "xmlns")) + t = SOAP_STR_EOS; + else + t = NULL; + for (tp = soap->attributes; tp; tp = tp->next) + if (!SOAP_STRCMP(tp->name, soap->tmpbuf)) + break; + if (!tp) + { tp = (struct soap_attribute*)SOAP_MALLOC(sizeof(struct soap_attribute) + strlen(soap->tmpbuf)); + if (!tp) + return soap->error = SOAP_EOM; + strcpy(tp->name, soap->tmpbuf); + tp->value = NULL; + tp->size = 0; + tp->next = soap->attributes; + soap->attributes = tp; + } + while (soap_blank(c)) + c = soap_get(soap); + if (c == '=') + { do c = soap_get(soap); + while (soap_blank(c)); + if (c != SOAP_QT && c != SOAP_AP) + { soap_unget(soap, c); + c = ' '; /* blank delimiter */ + } + if (soap_getattrval(soap, tp->value, tp->size, c)) + { +#ifdef WITH_FAST + if (soap->error != SOAP_EOM) + return soap->error; + soap->error = SOAP_OK; + soap->labidx = 0; + if (soap_append_lab(soap, tp->value, tp->size)) + return soap->error; + SOAP_FREE(tp->value); + for (;;) + { if (soap_getattrval(soap, soap->labbuf + soap->labidx, soap->lablen - soap->labidx, c)) + { if (soap->error != SOAP_EOM) + return soap->error; + soap->error = SOAP_OK; + soap->labidx = soap->lablen; + if (soap_append_lab(soap, NULL, 0)) + return soap->error; + } + else + break; + } + tp->size = soap->lablen; + if (!(tp->value = (char*)SOAP_MALLOC(tp->size))) + return soap->error = SOAP_EOM; + memcpy(tp->value, soap->labbuf, soap->lablen); +#else + size_t n; + if (soap->error != SOAP_EOM) + return soap->error; + soap->error = SOAP_OK; + if (soap_new_block(soap)) + return soap->error; + for (;;) + { if (!(s = (char*)soap_push_block(soap, SOAP_BLKLEN))) + return soap->error; + if (soap_getattrval(soap, s, SOAP_BLKLEN, c)) + { if (soap->error != SOAP_EOM) + return soap->error; + soap->error = SOAP_OK; + } + else + break; + } + n = tp->size + soap->blist->size; + if (!(s = (char*)SOAP_MALLOC(n))) + return soap->error = SOAP_EOM; + if (tp->value) + { memcpy(s, tp->value, tp->size); + SOAP_FREE(tp->value); + } + soap_save_block(soap, s + tp->size, 0); + tp->value = s; + tp->size = n; +#endif + } + do c = soap_get(soap); + while (soap_blank(c)); + tp->visible = 2; /* seen this attribute w/ value */ + } + else + tp->visible = 1; /* seen this attribute w/o value */ + if (t && tp->value) + { if (soap_push_namespace(soap, t, tp->value)) + return soap->error; + tp->visible = 0; + } + } + if ((int)c == EOF) + return soap->error = SOAP_EOF; + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible && tp->value) + { if (!strcmp(tp->name, "id")) + { *soap->id = '#'; + strncpy(soap->id + 1, tp->value, sizeof(soap->id) - 2); + soap->id[sizeof(soap->id)-1] = '\0'; + } + else if (!strcmp(tp->name, "href")) + { strncpy(soap->href, tp->value, sizeof(soap->href) - 1); + soap->href[sizeof(soap->href)-1] = '\0'; + } + else if ((soap->version == 2 || (soap->mode & SOAP_XML_GRAPH)) && !strcmp(tp->name, "ref")) + { *soap->href = '#'; + strncpy(soap->href + 1, tp->value, sizeof(soap->href) - 2); + soap->href[sizeof(soap->href)-1] = '\0'; + } + else if (!soap_match_tag(soap, tp->name, "xsi:type")) + { strncpy(soap->type, tp->value, sizeof(soap->type) - 1); + soap->type[sizeof(soap->type)-1] = '\0'; + } + else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:arrayType")) + { s = soap_strrchr(tp->value, '['); + if (s && (size_t)(s - tp->value) < sizeof(soap->arrayType)) + { strncpy(soap->arrayType, tp->value, s - tp->value); + soap->arrayType[s - tp->value] = '\0'; + strncpy(soap->arraySize, s, sizeof(soap->arraySize) - 1); + } + else + strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1); + soap->arraySize[sizeof(soap->arrayType)-1] = '\0'; + soap->arrayType[sizeof(soap->arrayType)-1] = '\0'; + } + else if (soap->version == 2 && !soap_match_tag(soap, tp->name, "SOAP-ENC:itemType")) + strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1); + else if (soap->version == 2 && !soap_match_tag(soap, tp->name, "SOAP-ENC:arraySize")) + strncpy(soap->arraySize, tp->value, sizeof(soap->arraySize) - 1); + else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:offset")) + strncpy(soap->arrayOffset, tp->value, sizeof(soap->arrayOffset)); + else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:position")) + soap->position = soap_getposition(tp->value, soap->positions); + else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:root")) + soap->root = ((!strcmp(tp->value, "1") || !strcmp(tp->value, "true"))); + else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:actor") + || !soap_match_tag(soap, tp->name, "SOAP-ENV:role")) + { if ((!soap->actor || strcmp(soap->actor, tp->value)) + && strcmp(tp->value, "http://schemas.xmlsoap.org/soap/actor/next") + && strcmp(tp->value, "http://www.w3.org/2003/05/soap-envelope/role/next")) + soap->other = 1; + } + else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand") + && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true"))) + soap->mustUnderstand = 1; + else if ((!soap_match_tag(soap, tp->name, "xsi:null") + || !soap_match_tag(soap, tp->name, "xsi:nil")) + && (!strcmp(tp->value, "1") + || !strcmp(tp->value, "true"))) + soap->null = 1; + } + } + if (!(soap->body = (c != '/'))) + do c = soap_get(soap); + while (soap_blank(c)); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_retry(struct soap *soap) +{ soap->peeked = 1; + soap->error = SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_revert(struct soap *soap) +{ if (!soap->peeked) + { soap->peeked = 1; + if (soap->body) + soap->level--; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reverting last element (level=%u)\n", soap->level)); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_string_out(struct soap *soap, const char *s, int flag) +{ register const char *t; + register soap_wchar c; + register soap_wchar mask = 0x80000000; +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { soap->dom->data = soap_strdup(soap, s); /* check EOM */ + return SOAP_OK; + } +#endif + if (soap->mode & SOAP_C_UTFSTRING) + mask = 0; + t = s; + while ((c = *t++)) + { switch (c) + { + case 9: + if (flag) + { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, " ", 5)) + return soap->error; + s = t; + } + break; + case 10: + if (flag || !(soap->mode & SOAP_XML_CANONICAL)) + { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, " ", 5)) + return soap->error; + s = t; + } + break; + case 13: + if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, " ", 5)) + return soap->error; + s = t; + break; + case '&': + if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&", 5)) + return soap->error; + s = t; + break; + case '<': + if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "<", 4)) + return soap->error; + s = t; + break; + case '>': + if (!flag) + { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, ">", 4)) + return soap->error; + s = t; + } + break; + case '"': + if (flag) + { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, """, 6)) + return soap->error; + s = t; + } + break; + default: +#ifdef HAVE_MBTOWC + if (soap->mode & SOAP_C_MBSTRING) + { wchar_t wc; + register int m = mbtowc(&wc, t - 1, MB_CUR_MAX); + if (m > 0 && wc != c) + { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, wc)) + return soap->error; + s = t + m - 1; + continue; + } + } +#endif + if (c & mask) + { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned char)c)) + return soap->error; + s = t; + } + } + } + return soap_send_raw(soap, s, t - s - 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_string_in(struct soap *soap, int flag, long minlen, long maxlen) +{ register char *s; + char *t = NULL; + register size_t i; + register long l = 0; + register int n = 0; + register int m = 0; + register soap_wchar c; +#ifdef HAVE_WCTOMB + char buf[MB_LEN_MAX > 8 ? MB_LEN_MAX : 8]; +#else + char buf[8]; +#endif +#ifdef WITH_CDATA + if (!flag) + { register int state = 0; +#ifdef WITH_FAST + soap->labidx = 0; /* use look-aside buffer */ +#else + if (soap_new_block(soap)) + return NULL; +#endif + for (;;) + { +#ifdef WITH_FAST + register size_t k; + if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */ + return NULL; + s = soap->labbuf + soap->labidx; /* space to populate */ + k = soap->lablen - soap->labidx; /* number of bytes available */ + soap->labidx = soap->lablen; /* claim this space */ +#else + register size_t k = SOAP_BLKLEN; + if (!(s = (char*)soap_push_block(soap, k))) + return NULL; +#endif + for (i = 0; i < k; i++) + { if (m > 0) + { *s++ = *t++; /* copy multibyte characters */ + m--; + continue; + } + c = soap_getchar(soap); + if ((int)c == EOF) + goto end; + if (c >= 0x80 && !(soap->mode & SOAP_ENC_LATIN)) + { soap_unget(soap, c); + c = soap_getutf8(soap); + if (soap->mode & SOAP_C_UTFSTRING) + { if ((c & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP) + { c &= 0x7FFFFFFF; + t = buf; + if (c < 0x0800) + *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); + else + { if (c < 0x010000) + *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + else + { if (c < 0x200000) + *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + else + { if (c < 0x04000000) + *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + else + { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + } + *t++ = (char)(0x80 | (c & 0x3F)); + m = (int)(t - buf) - 1; + t = buf; + *s++ = *t++; + continue; + } + } + } + switch (state) + { case 1: + if (c == ']') + state = 4; + *s++ = c; + continue; + case 2: + if (c == '-') + state = 6; + *s++ = c; + continue; + case 3: + if (c == '?') + state = 8; + *s++ = c; + continue; + /* CDATA */ + case 4: + if (c == ']') + state = 5; + else + state = 1; + *s++ = c; + continue; + case 5: + if (c == '>') + state = 0; + else + state = 1; + *s++ = c; + continue; + /* comment */ + case 6: + if (c == '-') + state = 7; + else + state = 2; + *s++ = c; + continue; + case 7: + if (c == '>') + state = 0; + else + state = 2; + *s++ = c; + continue; + /* PI */ + case 8: + if (c == '>') + state = 0; + else + state = 3; + *s++ = c; + continue; + } + switch (c) + { + case '/': + if (n > 0) + { c = soap_getchar(soap); + if (c == '>') + n--; + soap_unget(soap, c); + } + *s++ = '/'; + break; + case '<': + c = soap_getchar(soap); + if (c == '/') + { if (n == 0) + { c = SOAP_TT; + goto end; + } + n--; + } + else if (c == '!') + { c = soap_getchar(soap); + if (c == '[') + { do c = soap_getchar(soap); + while ((int)c != EOF && c != '['); + if ((int)c == EOF) + goto end; + t = (char*)"![CDATA["; + m = 8; + state = 1; + } + else if (c == '-') + { if ((c = soap_getchar(soap)) == '-') + state = 2; + t = (char*)"!-"; + m = 2; + soap_unget(soap, c); + } + else + { t = (char*)"!"; + m = 1; + soap_unget(soap, c); + } + *s++ = '<'; + break; + } + else if (c == '?') + state = 3; + else + n++; + soap_unget(soap, c); + *s++ = '<'; + break; + case '>': + *s++ = '>'; + break; + case '"': + *s++ = '"'; + break; + default: +#ifdef HAVE_WCTOMB + if (soap->mode & SOAP_C_MBSTRING) + { m = wctomb(buf, c & 0x7FFFFFFF); + if (m >= 1) + { t = buf; + *s++ = *t++; + m--; + } + else + *s++ = SOAP_UNKNOWN_CHAR; + } + else +#endif + *s++ = (char)(c & 0xFF); + } + l++; + if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); + soap->error = SOAP_LENGTH; + return NULL; + } + } + } + } +#endif +#ifdef WITH_FAST + soap->labidx = 0; /* use look-aside buffer */ +#else + if (soap_new_block(soap)) + return NULL; +#endif + for (;;) + { +#ifdef WITH_FAST + register size_t k; + if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */ + return NULL; + s = soap->labbuf + soap->labidx; /* space to populate */ + k = soap->lablen - soap->labidx; /* number of bytes available */ + soap->labidx = soap->lablen; /* claim this space */ +#else + register size_t k = SOAP_BLKLEN; + if (!(s = (char*)soap_push_block(soap, k))) + return NULL; +#endif + for (i = 0; i < k; i++) + { if (m > 0) + { *s++ = *t++; /* copy multibyte characters */ + m--; + continue; + } + if (soap->mode & SOAP_C_UTFSTRING) + { if (((c = soap_get(soap)) & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP) + { c &= 0x7FFFFFFF; + t = buf; + if (c < 0x0800) + *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); + else + { if (c < 0x010000) + *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + else + { if (c < 0x200000) + *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + else + { if (c < 0x04000000) + *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + else + { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + } + *t++ = (char)(0x80 | (c & 0x3F)); + m = (int)(t - buf) - 1; + t = buf; + *s++ = *t++; + continue; + } + } + else + c = soap_getutf8(soap); + switch (c) + { + case SOAP_TT: + if (n == 0) + goto end; + n--; + *s++ = '<'; + t = (char*)"/"; + m = 1; + break; + case SOAP_LT: + n++; + *s++ = '<'; + break; + case SOAP_GT: + *s++ = '>'; + break; + case SOAP_QT: + *s++ = '"'; + break; + case SOAP_AP: + *s++ = '\''; + break; + case '/': + if (n > 0) + { c = soap_get(soap); + if (c == SOAP_GT) + n--; + soap_unget(soap, c); + } + *s++ = '/'; + break; + case '<' | 0x80000000: + if (flag) + *s++ = '<'; + else + { *s++ = '&'; + t = (char*)"lt;"; + m = 3; + } + break; + case '>' | 0x80000000: + if (flag) + *s++ = '>'; + else + { *s++ = '&'; + t = (char*)"gt;"; + m = 3; + } + break; + case '"' | 0x80000000: + if (flag) + *s++ = '"'; + else + { *s++ = '&'; + t = (char*)"quot;"; + m = 5; + } + break; + case '\'' | 0x80000000: + if (flag) + *s++ = '\''; + else + { *s++ = '&'; + t = (char*)"apos;"; + m = 5; + } + break; + default: + if ((int)c == EOF) + goto end; +#ifdef HAVE_WCTOMB + if (soap->mode & SOAP_C_MBSTRING) + { m = wctomb(buf, c & 0x7FFFFFFF); + if (m >= 1) + { t = buf; + *s++ = *t++; + m--; + } + else + *s++ = SOAP_UNKNOWN_CHAR; + } + else +#endif + *s++ = (char)(c & 0xFF); + } + l++; + if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); + soap->error = SOAP_LENGTH; + return NULL; + } + } + } +end: + soap_unget(soap, c); + *s = '\0'; +#ifdef WITH_FAST + t = soap_strdup(soap, soap->labbuf); +#else + soap_size_block(soap, i+1); + t = soap_save_block(soap, NULL, 0); +#endif + if ((soap->mode & SOAP_XML_STRICT) && l < minlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen)); + soap->error = SOAP_LENGTH; + return NULL; + } + if (flag == 2) + if (soap_s2QName(soap, t, &t)) + return NULL; + return t; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_wstring_out(struct soap *soap, const wchar_t *s, int flag) +{ const char *t; + char tmp; + register soap_wchar c; +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { soap->dom->wide = NULL; /* soap_malloc() ??? */ + return SOAP_OK; + } +#endif + while ((c = *s++)) + { switch (c) + { + case 9: + if (flag) + t = " "; + else + t = "\t"; + break; + case 10: + if (flag || !(soap->mode & SOAP_XML_CANONICAL)) + t = " "; + else + t = "\n"; + break; + case 13: + t = " "; + break; + case '&': + t = "&"; + break; + case '<': + t = "<"; + break; + case '>': + if (flag) + t = ">"; + else + t = ">"; + break; + case '"': + if (flag) + t = """; + else + t = "\""; + break; + default: + if (c > 0 && c < 0x80) + { tmp = (char)c; + if (soap_send_raw(soap, &tmp, 1)) + return soap->error; + } + else if (soap_pututf8(soap, (unsigned long)c)) + return soap->error; + continue; + } + if (soap_send(soap, t)) + return soap->error; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +wchar_t * +SOAP_FMAC2 +soap_wstring_in(struct soap *soap, int flag, long minlen, long maxlen) +{ wchar_t *s; + register int i, n = 0; + register long l = 0; + register soap_wchar c; + const char *t = NULL; + if (soap_new_block(soap)) + return NULL; + for (;;) + { if (!(s = (wchar_t*)soap_push_block(soap, sizeof(wchar_t)*SOAP_BLKLEN))) + return NULL; + for (i = 0; i < SOAP_BLKLEN; i++) + { if (t) + { *s++ = (wchar_t)*t++; + if (!*t) + t = NULL; + continue; + } + c = soap_getutf8(soap); + switch (c) + { + case SOAP_TT: + if (n == 0) + goto end; + n--; + *s++ = '<'; + soap_unget(soap, '/'); + break; + case SOAP_LT: + n++; + *s++ = '<'; + break; + case SOAP_GT: + *s++ = '>'; + break; + case SOAP_QT: + *s++ = '"'; + break; + case SOAP_AP: + *s++ = '\''; + break; + case '/': + if (n > 0) + { c = soap_getutf8(soap); + if (c == SOAP_GT) + n--; + soap_unget(soap, c); + } + *s++ = '/'; + break; + case '<': + if (flag) + *s++ = (soap_wchar)'<'; + else + { *s++ = (soap_wchar)'&'; + t = "lt;"; + } + break; + case '>': + if (flag) + *s++ = (soap_wchar)'>'; + else + { *s++ = (soap_wchar)'&'; + t = "gt;"; + } + break; + case '"': + if (flag) + *s++ = (soap_wchar)'"'; + else + { *s++ = (soap_wchar)'&'; + t = "quot;"; + } + break; + default: + if ((int)c == EOF) + goto end; + *s++ = (wchar_t)c & 0x7FFFFFFF; + } + l++; + if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); + soap->error = SOAP_LENGTH; + return NULL; + } + } + } +end: + soap_unget(soap, c); + *s = '\0'; + soap_size_block(soap, sizeof(wchar_t) * (i + 1)); + if ((soap->mode & SOAP_XML_STRICT) && l < minlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen)); + soap->error = SOAP_LENGTH; + return NULL; + } + return (wchar_t*)soap_save_block(soap, NULL, 0); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_int2s(struct soap *soap, int n) +{ return soap_long2s(soap, (long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outint(struct soap *soap, const char *tag, int id, const int *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_long2s(soap, (long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2int(struct soap *soap, const char *s, int *p) +{ if (s) + { char *r; + *p = (int)soap_strtol(s, &r, 10); + if (*r) + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int * +SOAP_FMAC2 +soap_inint(struct soap *soap, const char *tag, int *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":int") + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (int*)soap_id_enter(soap, soap->id, p, t, sizeof(int), 0, NULL, NULL, NULL); + if (p) + { if (soap_s2int(soap, soap_value(soap), p)) + return NULL; + } + p = (int*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(int), 0, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_long2s(struct soap *soap, long n) +{ sprintf(soap->tmpbuf, "%ld", n); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outlong(struct soap *soap, const char *tag, int id, const long *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_long2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2long(struct soap *soap, const char *s, long *p) +{ if (s) + { char *r; + *p = soap_strtol(s, &r, 10); + if (*r) + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +long * +SOAP_FMAC2 +soap_inlong(struct soap *soap, const char *tag, long *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":int") + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (long*)soap_id_enter(soap, soap->id, p, t, sizeof(long), 0, NULL, NULL, NULL); + if (p) + { if (soap_s2long(soap, soap_value(soap), p)) + return NULL; + } + p = (long*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(long), 0, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_LONG642s(struct soap *soap, LONG64 n) +{ sprintf(soap->tmpbuf, SOAP_LONG_FORMAT, n); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outLONG64(struct soap *soap, const char *tag, int id, const LONG64 *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_LONG642s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2LONG64(struct soap *soap, const char *s, LONG64 *p) +{ if (s && sscanf(s, SOAP_LONG_FORMAT, p) != 1) + soap->error = SOAP_TYPE; + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +LONG64 * +SOAP_FMAC2 +soap_inLONG64(struct soap *soap, const char *tag, LONG64 *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":integer") + && soap_match_tag(soap, soap->type, ":positiveInteger") + && soap_match_tag(soap, soap->type, ":negativeInteger") + && soap_match_tag(soap, soap->type, ":nonPositiveInteger") + && soap_match_tag(soap, soap->type, ":nonNegativeInteger") + && soap_match_tag(soap, soap->type, ":long") + && soap_match_tag(soap, soap->type, ":int") + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (LONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(LONG64), 0, NULL, NULL, NULL); + if (p) + { if (soap_s2LONG64(soap, soap_value(soap), p)) + return NULL; + } + p = (LONG64*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(LONG64), 0, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_byte2s(struct soap *soap, char n) +{ return soap_long2s(soap, (long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outbyte(struct soap *soap, const char *tag, int id, const char *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_long2s(soap, (long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2byte(struct soap *soap, const char *s, char *p) +{ if (s) + { long n; + char *r; + n = soap_strtol(s, &r, 10); + if (*r || n < -128 || n > 127) + soap->error = SOAP_TYPE; + *p = (char)n; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_inbyte(struct soap *soap, const char *tag, char *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (char*)soap_id_enter(soap, soap->id, p, t, sizeof(char), 0, NULL, NULL, NULL); + if (p) + { if (soap_s2byte(soap, soap_value(soap), p)) + return NULL; + } + p = (char*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(char), 0, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_short2s(struct soap *soap, short n) +{ return soap_long2s(soap, (long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outshort(struct soap *soap, const char *tag, int id, const short *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_long2s(soap, (long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2short(struct soap *soap, const char *s, short *p) +{ if (s) + { long n; + char *r; + n = soap_strtol(s, &r, 10); + if (*r || n < -32768 || n > 32767) + soap->error = SOAP_TYPE; + *p = (short)n; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +short * +SOAP_FMAC2 +soap_inshort(struct soap *soap, const char *tag, short *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (short*)soap_id_enter(soap, soap->id, p, t, sizeof(short), 0, NULL, NULL, NULL); + if (p) + { if (soap_s2short(soap, soap_value(soap), p)) + return NULL; + } + p = (short*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(short), 0, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_float2s(struct soap *soap, float n) +{ const char *s; + if (soap_isnan((double)n)) + s = "NaN"; + else if (soap_ispinff(n)) + s = "INF"; + else if (soap_isninff(n)) + s = "-INF"; + else + { sprintf(soap->tmpbuf, soap->float_format, n); + s = soap->tmpbuf; + } + return s; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outfloat(struct soap *soap, const char *tag, int id, const float *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_float2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2float(struct soap *soap, const char *s, float *p) +{ if (s) + { if (!soap_tag_cmp(s, "INF")) + *p = FLT_PINFTY; + else if (!soap_tag_cmp(s, "+INF")) + *p = FLT_PINFTY; + else if (!soap_tag_cmp(s, "-INF")) + *p = FLT_NINFTY; + else if (!soap_tag_cmp(s, "NaN")) + *p = FLT_NAN; + else + { +#ifdef HAVE_STRTOD + char *r; + *p = (float)strtod(s, &r); + if (*r) +#endif +#ifdef HAVE_SSCANF + if (sscanf(s, soap->float_format, p) != 1) + soap->error = SOAP_TYPE; +#else + soap->error = SOAP_TYPE; +#endif + } + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static int soap_isnumeric(struct soap *soap, const char *type) +{ if (soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":float") + && soap_match_tag(soap, soap->type, ":double") + && soap_match_tag(soap, soap->type, ":decimal") + && soap_match_tag(soap, soap->type, ":integer") + && soap_match_tag(soap, soap->type, ":positiveInteger") + && soap_match_tag(soap, soap->type, ":negativeInteger") + && soap_match_tag(soap, soap->type, ":nonPositiveInteger") + && soap_match_tag(soap, soap->type, ":nonNegativeInteger") + && soap_match_tag(soap, soap->type, ":long") + && soap_match_tag(soap, soap->type, ":int") + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte") + && soap_match_tag(soap, soap->type, ":unsignedLong") + && soap_match_tag(soap, soap->type, ":unsignedInt") + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return SOAP_ERR; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +float * +SOAP_FMAC2 +soap_infloat(struct soap *soap, const char *tag, float *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type != '\0' && soap_isnumeric(soap, type)) + return NULL; +#endif + p = (float*)soap_id_enter(soap, soap->id, p, t, sizeof(float), 0, NULL, NULL, NULL); + if (p) + { if (soap_s2float(soap, soap_value(soap), p)) + return NULL; + } + p = (float*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(float), 0, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_double2s(struct soap *soap, double n) +{ const char *s; + if (soap_isnan(n)) + s = "NaN"; + else if (soap_ispinfd(n)) + s = "INF"; + else if (soap_isninfd(n)) + s = "-INF"; + else + { sprintf(soap->tmpbuf, soap->double_format, n); + s = soap->tmpbuf; + } + return s; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outdouble(struct soap *soap, const char *tag, int id, const double *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_double2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2double(struct soap *soap, const char *s, double *p) +{ if (s) + { if (!soap_tag_cmp(s, "INF")) + *p = DBL_PINFTY; + else if (!soap_tag_cmp(s, "+INF")) + *p = DBL_PINFTY; + else if (!soap_tag_cmp(s, "-INF")) + *p = DBL_NINFTY; + else if (!soap_tag_cmp(s, "NaN")) + *p = DBL_NAN; + else + { +#ifdef HAVE_STRTOD + char *r; + *p = strtod(s, &r); + if (*r) +#endif +#ifdef HAVE_SSCANF + if (sscanf(s, soap->double_format, p) != 1) + soap->error = SOAP_TYPE; +#else + soap->error = SOAP_TYPE; +#endif + } + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +double * +SOAP_FMAC2 +soap_indouble(struct soap *soap, const char *tag, double *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type != '\0' && soap_isnumeric(soap, type)) + return NULL; +#endif + p = (double*)soap_id_enter(soap, soap->id, p, t, sizeof(double), 0, NULL, NULL, NULL); + if (p) + { if (soap_s2double(soap, soap_value(soap), p)) + return NULL; + } + p = (double*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(double), 0, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_unsignedByte2s(struct soap *soap, unsigned char n) +{ return soap_unsignedLong2s(soap, (unsigned long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outunsignedByte(struct soap *soap, const char *tag, int id, const unsigned char *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2unsignedByte(struct soap *soap, const char *s, unsigned char *p) +{ if (s) + { unsigned long n; + char *r; + n = soap_strtoul(s, &r, 10); + if (*r || n > 255) + soap->error = SOAP_TYPE; + *p = (unsigned char)n; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +unsigned char * +SOAP_FMAC2 +soap_inunsignedByte(struct soap *soap, const char *tag, unsigned char *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (unsigned char*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned char), 0, NULL, NULL, NULL); + if (p) + { if (soap_s2unsignedByte(soap, soap_value(soap), p)) + return NULL; + } + p = (unsigned char*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(unsigned char), 0, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_unsignedShort2s(struct soap *soap, unsigned short n) +{ return soap_unsignedLong2s(soap, (unsigned long)n); +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outunsignedShort(struct soap *soap, const char *tag, int id, const unsigned short *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2unsignedShort(struct soap *soap, const char *s, unsigned short *p) +{ if (s) + { unsigned long n; + char *r; + n = soap_strtoul(s, &r, 10); + if (*r || n > 65535) + soap->error = SOAP_TYPE; + *p = (unsigned short)n; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +unsigned short * +SOAP_FMAC2 +soap_inunsignedShort(struct soap *soap, const char *tag, unsigned short *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (unsigned short*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned short), 0, NULL, NULL, NULL); + if (p) + { if (soap_s2unsignedShort(soap, soap_value(soap), p)) + return NULL; + } + p = (unsigned short*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(unsigned short), 0, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_unsignedInt2s(struct soap *soap, unsigned int n) +{ return soap_unsignedLong2s(soap, (unsigned long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outunsignedInt(struct soap *soap, const char *tag, int id, const unsigned int *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2unsignedInt(struct soap *soap, const char *s, unsigned int *p) +{ if (s) + { char *r; + *p = (unsigned int)soap_strtoul(s, &r, 10); + if (*r) + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +unsigned int * +SOAP_FMAC2 +soap_inunsignedInt(struct soap *soap, const char *tag, unsigned int *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":unsignedInt") + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (unsigned int*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned int), 0, NULL, NULL, NULL); + if (p) + { if (soap_s2unsignedInt(soap, soap_value(soap), p)) + return NULL; + } + p = (unsigned int*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(unsigned int), 0, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_unsignedLong2s(struct soap *soap, unsigned long n) +{ sprintf(soap->tmpbuf, "%lu", n); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outunsignedLong(struct soap *soap, const char *tag, int id, const unsigned long *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_unsignedLong2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2unsignedLong(struct soap *soap, const char *s, unsigned long *p) +{ if (s) + { char *r; + *p = soap_strtoul(s, &r, 10); + if (*r) + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +unsigned long * +SOAP_FMAC2 +soap_inunsignedLong(struct soap *soap, const char *tag, unsigned long *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":unsignedInt") + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (unsigned long*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned long), 0, NULL, NULL, NULL); + if (p) + { if (soap_s2unsignedLong(soap, soap_value(soap), p)) + return NULL; + } + p = (unsigned long*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(unsigned long), 0, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_ULONG642s(struct soap *soap, ULONG64 n) +{ sprintf(soap->tmpbuf, SOAP_ULONG_FORMAT, n); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outULONG64(struct soap *soap, const char *tag, int id, const ULONG64 *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_ULONG642s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2ULONG64(struct soap *soap, const char *s, ULONG64 *p) +{ if (s && sscanf(s, SOAP_ULONG_FORMAT, p) != 1) + soap->error = SOAP_TYPE; + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +ULONG64 * +SOAP_FMAC2 +soap_inULONG64(struct soap *soap, const char *tag, ULONG64 *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":positiveInteger") + && soap_match_tag(soap, soap->type, ":nonNegativeInteger") + && soap_match_tag(soap, soap->type, ":unsignedLong") + && soap_match_tag(soap, soap->type, ":unsignedInt") + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } + p = (ULONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(ULONG64), 0, NULL, NULL, NULL); + if (p) + { if (soap_s2ULONG64(soap, soap_value(soap), p)) + return NULL; + } + p = (ULONG64*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(ULONG64), 0, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2string(struct soap *soap, const char *s, char **t) +{ *t = NULL; + if (s && !(*t = soap_strdup(soap, s))) + soap->error = SOAP_EOM; + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2QName(struct soap *soap, const char *s, char **t) +{ if (s) + { struct soap_nlist *np; + const char *p; + if (!strncmp(s, "xml:", 4)) + { *t = soap_strdup(soap, s); + return SOAP_OK; + } + np = soap->nlist; + p = strchr(s, ':'); + if (p) + { register int n = p - s; + while (np && (strncmp(np->id, s, n) || np->id[n])) + np = np->next; + p++; + } + else + { while (np && *np->id) + np = np->next; + p = s; + } + if (np) + { if (np->index >= 0 && soap->local_namespaces) + { register const char *q = soap->local_namespaces[np->index].id; + if (q) + { if ((*t = (char*)soap_malloc(soap, strlen(p) + strlen(q) + 2))) + sprintf(*t, "%s:%s", q, p); + return SOAP_OK; + } + } + if (np->ns) + { if ((*t = (char*)soap_malloc(soap, strlen(p) + strlen(np->ns) + 4))) + sprintf(*t, "\"%s\":%s", np->ns, p); + return SOAP_OK; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Namespace prefix of '%s' not defined (index=%d, URI=%s)\n", s, np->index, np->ns?np->ns:"")); + return soap->error = SOAP_NAMESPACE; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Namespace prefix of '%s' not defined, assuming empty namespace\n", s)); + if ((*t = (char*)soap_malloc(soap, strlen(p) + 4))) + sprintf(*t, "\"\":%s", p); + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_QName2s(struct soap *soap, const char *s) +{ struct Namespace *p; + char *t; + int n; + if (!s || *s != '"') + return s; + s++; + if ((p = soap->local_namespaces)) + { for (; p->id; p++) + { if (p->ns) + if (!soap_tag_cmp(s, p->ns)) + break; + if (p->in) + if (!soap_tag_cmp(s, p->in)) + break; + } + if (p && p->id) + { s = strchr(s, '"'); + if (s) + { t = (char*)soap_malloc(soap, strlen(p->id) + strlen(s)); + strcpy(t, p->id); + strcat(t, s + 1); + return t; + } + } + } + t = (char*)strchr(s, '"'); + if (t) + n = t - s; + else + n = 0; + t = soap_strdup(soap, s); + t[n] = '\0'; + sprintf(soap->tmpbuf, "xmlns:_%lu", soap->idnum++); + soap_set_attr(soap, soap->tmpbuf, t); + s = strchr(s, '"'); + if (s) + { t = (char*)soap_malloc(soap, strlen(soap->tmpbuf) + strlen(s) - 6); + strcpy(t, soap->tmpbuf + 6); + strcat(t, s + 1); + } + return t; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outstring(struct soap *soap, const char *tag, int id, char *const*p, const char *type, int n) +{ id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n); + if (id < 0 + || soap_element_begin_out(soap, tag, id, type) + || soap_string_out(soap, *p, 0) + || soap_element_end_out(soap, tag)) + return soap->error; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char ** +SOAP_FMAC2 +soap_instring(struct soap *soap, const char *tag, char **p, const char *type, int t, int flag, long minlen, long maxlen) +{ if (soap_element_begin_in(soap, tag, 1)) + return NULL; + if (!p) + if (!(p = (char**)soap_malloc(soap, sizeof(char*)))) + return NULL; + if (soap->body) + { *p = soap_string_in(soap, flag, minlen, maxlen); + if (!*p || !(char*)soap_id_enter(soap, soap->id, *p, t, sizeof(char*), 0, NULL, NULL, NULL)) + return NULL; + } + else + *p = NULL; + p = (char**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(char**), 0); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outwstring(struct soap *soap, const char *tag, int id, wchar_t *const*p, const char *type, int n) +{ id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n); + if (id < 0 + || soap_element_begin_out(soap, tag, id, type) + || soap_wstring_out(soap, *p, 0) + || soap_element_end_out(soap, tag)) + return soap->error; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +wchar_t ** +SOAP_FMAC2 +soap_inwstring(struct soap *soap, const char *tag, wchar_t **p, const char *type, int t, long minlen, long maxlen) +{ if (soap_element_begin_in(soap, tag, 1)) + return NULL; + if (!p) + if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*)))) + return NULL; + if (soap->body) + { *p = soap_wstring_in(soap, 1, minlen, maxlen); + if (!*p || !(wchar_t*)soap_id_enter(soap, soap->id, *p, t, sizeof(wchar_t*), 0, NULL, NULL, NULL)) + return NULL; + } + else + *p = NULL; + p = (wchar_t**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(wchar_t**), 0); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static time_t +soap_timegm(struct tm *T) +{ +#if defined(HAVE_TIMEGM) + return timegm(T); +#elif defined(HAVE_GETTIMEOFDAY) + struct timezone t; + struct timeval tv; + memset((void*)&t, 0, sizeof(t)); + gettimeofday(&tv, &t); + T->tm_min -= t.tz_minuteswest - (t.tz_dsttime != 0)*60; + T->tm_isdst = 0; + return mktime(T); +/* WR[ */ + /* The following define was added for VxWorks*/ +#elif defined(HAVE_MKTIME) + /* FOR VXWORKS: + vxWorks does not seem to have any variable representation of time zones, but + timezone information can be set in INSTALL_DIR/target/h/private/timeP.h header + file, by setting the ZONEBUFFER define. The ZONEBUFFER define follows this + format: + name_of_zone:<(unused)>:time_in_minutes_from_UTC:daylight_start:daylight_end + To calculate local time, the value of time_in_minutes_from_UTC is subtracted + from UTC; time_in_minutes_from_UTC must be positive. Daylight information is + expressed as mmddhh (month-day-hour), for example: + UTC::0:040102:100102 + */ + return mktime(T); +/* ]WR */ +#elif defined(HAVE_FTIME) + struct timeb t; + memset((void*)&t, 0, sizeof(t)); + t.timezone = 0; + t.dstflag = -1; + ftime(&t); + T->tm_min -= t.timezone - (t.dstflag != 0)*60; + T->tm_isdst = 0; + return mktime(T); +#else +#warning "time_t (de)serialization is not MT safe on this platform" + time_t t; + char *tz = getenv("TZ"); + putenv("TZ=UTC"); + tzset(); + t = mktime(T); + if (tz) + { char tmp[16]; + strcpy(tmp, "TZ="); + strncat(tmp, tz, 12); + tmp[15] = '\0'; + putenv(tmp); + } + else + putenv("TZ="); + tzset(); + return t; +#endif +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_dateTime2s(struct soap *soap, time_t n) +{ struct tm T; + struct tm *pT = &T; +#if defined(HAVE_GMTIME_R) + if (gmtime_r(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); +/* WR[ */ + /* The following defines were added for VxWorks*/ +#elif defined(HAVE_PGMTIME_R) + if (gmtime_r(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); +#elif defined(HAVE_PGMTIME) + if (gmtime(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); +/* ]WR */ +#elif defined(HAVE_GMTIME) + if ((pT = gmtime(&n))) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); +#elif defined(HAVE_GETTIMEOFDAY) + struct timezone tz; + memset((void*)&tz, 0, sizeof(tz)); +#if defined(HAVE_LOCALTIME_R) + if (localtime_r(&n, pT)) + { struct timeval tv; + gettimeofday(&tv, &tz); + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(tz.tz_dsttime!=0), abs(tz.tz_minuteswest)%60); + } +#else + if ((pT = localtime(&n))) + { struct timeval tv; + gettimeofday(&tv, &tz); + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(tz.tz_dsttime!=0), abs(tz.tz_minuteswest)%60); + } +#endif +#elif defined(HAVE_FTIME) + struct timeb t; + memset((void*)&t, 0, sizeof(t)); +#if defined(HAVE_LOCALTIME_R) + if (localtime_r(&n, pT)) + { ftime(&t); + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(t.dstflag!=0), abs(t.timezone)%60); + } +/* WR[ */ + /* The following defines were added for VxWorks*/ +#elif defined(HAVE_PLOCALTIME_R) + if (localtime_r(&n, pT)) + { strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf+strlen(soap->tmpbuf), "%+03d:%02d", t.timezone/60, abs(t.timezone)%60); + } +/* ]WR */ +#else + if ((pT = localtime(&n))) + { ftime(&t); + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(t.dstflag!=0), abs(t.timezone)%60); + } +#endif +#elif defined(HAVE_LOCALTIME_R) + if (localtime_r(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); +/* WR[ */ + /* The following defines were added for VxWorks*/ +#elif defined(HAVE_PLOCALTIME_R) + if (localtime_r(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); +/* ]WR */ +#else + if ((pT = localtime(&n))) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); +#endif + else + strcpy(soap->tmpbuf, "1969-12-31T23:59:59Z"); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outdateTime(struct soap *soap, const char *tag, int id, const time_t *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_dateTime2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2dateTime(struct soap *soap, const char *s, time_t *p) +{ if (s) + { struct tm T; + char zone[16]; + memset((void*)&T, 0, sizeof(T)); + zone[sizeof(zone)-1] = '\0'; + sscanf(s, "%d-%d-%dT%d:%d:%d%15s", &T.tm_year, &T.tm_mon, &T.tm_mday, &T.tm_hour, &T.tm_min, &T.tm_sec, zone); + if (T.tm_year == 1) + T.tm_year = 70; + else + T.tm_year -= 1900; + T.tm_mon--; + if (*zone) + { if (*zone == '.') + { for (s = zone + 1; *s; s++) + if (*s < '0' || *s > '9') + break; + } + else + s = zone; + if (*s != 'Z') + { int h = 0, m = 0; + sscanf(s, "%d:%d", &h, &m); + T.tm_hour -= h; + if (h >= 0) + T.tm_min -= m; + else + T.tm_min += m; + } + *p = soap_timegm(&T); + } + else + *p = mktime(&T); /* no time zone: suppose it is localtime? */ + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +time_t * +SOAP_FMAC2 +soap_indateTime(struct soap *soap, const char *tag, time_t *p, const char * type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":dateTime")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } + p = (time_t*)soap_id_enter(soap, soap->id, p, t, sizeof(time_t), 0, NULL, NULL, NULL); + if (p) + { if (soap_s2dateTime(soap, soap_value(soap), p)) + return NULL; + } + p = (time_t*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(time_t), 0, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outliteral(struct soap *soap, const char *tag, char *const*p) +{ int i; + const char *t = NULL; + if (tag && *tag != '-') + { if ((t = strchr(tag, ':'))) + { strncpy(soap->tmpbuf, tag, t-tag); + soap->tmpbuf[t-tag] = '\0'; + for (i = 0; soap->local_namespaces[i].id; i++) + if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id)) + break; + t++; + sprintf(soap->tmpbuf, "<%s xmlns=\"%s\">", t, soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS); + } + else + { t = tag; + sprintf(soap->tmpbuf, "<%s>", tag); + } + if (soap_send(soap, soap->tmpbuf)) + return soap->error; + } + if (p && *p) + { if (soap_send(soap, *p)) + return soap->error; + } + if (t) + { sprintf(soap->tmpbuf, "", t); + return soap_send(soap, soap->tmpbuf); + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char ** +SOAP_FMAC2 +soap_inliteral(struct soap *soap, const char *tag, char **p) +{ if (soap_element_begin_in(soap, tag, 1)) + return NULL; + if (!p) + if (!(p = (char**)soap_malloc(soap, sizeof(char*)))) + return NULL; + if (soap->null) + *p = NULL; + else if (soap->body) + *p = soap_string_in(soap, 0, -1, -1); + else + *p = NULL; + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outwliteral(struct soap *soap, const char *tag, wchar_t *const*p) +{ int i; + const char *t = NULL; + wchar_t c; + const wchar_t *s; + if (tag && *tag != '-') + { if (tag && (t = strchr(tag, ':'))) + { strncpy(soap->tmpbuf, tag, t-tag); + soap->tmpbuf[t-tag] = '\0'; + for (i = 0; soap->local_namespaces[i].id; i++) + if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id)) + break; + t++; + sprintf(soap->tmpbuf, "<%s xmlns=\"%s\">", t, soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS); + } + else + { t = tag; + sprintf(soap->tmpbuf, "<%s>", tag); + } + if (soap_send(soap, soap->tmpbuf)) + return soap->error; + } + if (p) + { s = *p; + while ((c = *s++)) + if (soap_pututf8(soap, (unsigned char)c)) + return soap->error; + } + if (t) + { sprintf(soap->tmpbuf, "", t); + return soap_send(soap, soap->tmpbuf); + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +wchar_t ** +SOAP_FMAC2 +soap_inwliteral(struct soap *soap, const char *tag, wchar_t **p) +{ if (soap_element_begin_in(soap, tag, 1)) + return NULL; + if (!p) + if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*)))) + return NULL; + if (soap->null) + *p = NULL; + else if (soap->body) + *p = soap_wstring_in(soap, 0, -1, -1); + else + *p = NULL; + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char * +SOAP_FMAC2 +soap_value(struct soap *soap) +{ size_t i; + soap_wchar c = 0; + char *s = soap->tmpbuf; + if (!soap->body) + return SOAP_STR_EOS; + for (i = 0; i < sizeof(soap->tmpbuf) - 1; i++) + { c = soap_get(soap); + if (c == SOAP_TT || (int)c == EOF || soap_blank(c)) + break; + *s++ = (char)c; + } + if ((int)c == EOF || c == SOAP_TT) + soap_unget(soap, c); + *s = '\0'; + return soap->tmpbuf; /* return non-null pointer */ +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getline(struct soap *soap, char *s, int len) +{ int i = len; + soap_wchar c = 0; + for (;;) + { while (--i > 0) + { c = soap_getchar(soap); + if (c == '\r') + break; + if ((int)c == EOF) + return soap->error = SOAP_EOF; + *s++ = (char)c; + } + c = soap_getchar(soap); + if (c == '\n') + { *s = '\0'; + if (i+1 == len) /* empty line: end of HTTP header */ + break; + c = soap_unget(soap, soap_getchar(soap)); + if (c != ' ' && c != '\t') /* HTTP line continuation? */ + break; + } + else if ((int)c == EOF) + return soap->error = SOAP_EOF; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static size_t +soap_count_attachments(struct soap *soap) +{ +#ifndef WITH_LEANER + register struct soap_multipart *content; + register size_t count = soap->count; + if (soap->mode & SOAP_ENC_DIME) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of DIME attachments\n")); + for (content = soap->dime.first; content; content = content->next) + { count += 12 + ((content->size+3)&(~3)); + if (content->id) + count += ((strlen(content->id)+3)&(~3)); + if (content->type) + count += ((strlen(content->type)+3)&(~3)); + if (content->options) + count += ((((unsigned char)content->options[2] << 8) | ((unsigned char)content->options[3]))+7)&(~3); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of DIME attachment %lu bytes\n", (unsigned long)content->size)); + } + } + if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary) + { register size_t n = strlen(soap->mime.boundary); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of MIME attachments\n")); + for (content = soap->mime.first; content; content = content->next) + { register const char *s; + /* count \r\n--boundary\r\n */ + count += 6 + n; + /* count Content-Type: ...\r\n */ + if (content->type) + count += 16 + strlen(content->type); + s = soap_str_code(mime_codes, content->encoding); + /* count Content-Transfer-Encoding: ...\r\n */ + if (s) + count += 29 + strlen(s); + /* count Content-ID: ...\r\n */ + if (content->id) + count += 14 + strlen(content->id); + /* count Content-Location: ...\r\n */ + if (content->location) + count += 20 + strlen(content->location); + /* count Content-Description: ...\r\n */ + if (content->description) + count += 23 + strlen(content->location); + /* count \r\n...content */ + count += 2 + content->size; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of MIME attachment %lu bytes\n", (unsigned long)content->size)); + } + /* count \r\n--boundary--\r\n */ + count += 8 + n; + } + return count; +#else + return soap->count; +#endif +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static int +soap_putdimefield(struct soap *soap, const char *s, size_t n) +{ if (soap_send_raw(soap, s, n)) + return soap->error; + return soap_send_raw(soap, SOAP_STR_PADDING, -(long)n&3); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_dime_option(struct soap *soap, unsigned short optype, const char *option) +{ size_t n; + char *s = NULL; + if (option) + { n = strlen(option); + s = (char*)soap_malloc(soap, n + 5); + if (s) + { s[0] = optype >> 8; + s[1] = optype & 0xFF; + s[2] = n >> 8; + s[3] = n & 0xFF; + strcpy(s + 4, option); + } + } + return s; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putdimehdr(struct soap *soap) +{ unsigned char tmp[12]; + size_t optlen = 0, idlen = 0, typelen = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Put DIME header id='%s'\n", soap->dime.id?soap->dime.id:"")); + if (soap->dime.options) + optlen = (((unsigned char)soap->dime.options[2] << 8) | ((unsigned char)soap->dime.options[3])) + 4; + if (soap->dime.id) + idlen = strlen(soap->dime.id); + if (soap->dime.type) + typelen = strlen(soap->dime.type); + tmp[0] = SOAP_DIME_VERSION | (soap->dime.flags & 0x7); + tmp[1] = soap->dime.flags & 0xF0; + tmp[2] = optlen >> 8; + tmp[3] = optlen & 0xFF; + tmp[4] = idlen >> 8; + tmp[5] = idlen & 0xFF; + tmp[6] = typelen >> 8; + tmp[7] = typelen & 0xFF; + tmp[8] = soap->dime.size >> 24; + tmp[9] = (soap->dime.size >> 16) & 0xFF; + tmp[10] = (soap->dime.size >> 8) & 0xFF; + tmp[11] = soap->dime.size & 0xFF; + if (soap_send_raw(soap, (char*)tmp, 12) + || soap_putdimefield(soap, soap->dime.options, optlen) + || soap_putdimefield(soap, soap->dime.id, idlen) + || soap_putdimefield(soap, soap->dime.type, typelen)) + return soap->error; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putdime(struct soap *soap) +{ struct soap_multipart *content; + if (!(soap->mode & SOAP_ENC_DIME)) + return SOAP_OK; + for (content = soap->dime.first; content; content = content->next) + { void *handle; + soap->dime.size = content->size; + soap->dime.id = content->id; + soap->dime.type = content->type; + soap->dime.options = content->options; + soap->dime.flags = SOAP_DIME_VERSION | SOAP_DIME_MEDIA; + if (soap->fdimereadopen && ((handle = soap->fdimereadopen(soap, (void*)content->ptr, content->id, content->type, content->options)) || soap->error)) + { size_t size = content->size; + if (!handle) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadopen failed\n")); + return soap->error; + } + if (!content->size && ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE)) + { size_t chunksize = sizeof(soap->tmpbuf); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming DIME\n")); + do + { size = soap->fdimeread(soap, handle, soap->tmpbuf, chunksize); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread returned %lu bytes\n", (unsigned long)size)); + if (size < chunksize) + { soap->dime.flags &= ~SOAP_DIME_CF; + if (!content->next) + soap->dime.flags |= SOAP_DIME_ME; + } + else + soap->dime.flags |= SOAP_DIME_CF; + soap->dime.size = size; + if (soap_putdimehdr(soap) + || soap_putdimefield(soap, soap->tmpbuf, size)) + break; + if (soap->dime.id) + { soap->dime.flags &= ~(SOAP_DIME_MB | SOAP_DIME_MEDIA); + soap->dime.id = NULL; + soap->dime.type = NULL; + soap->dime.options = NULL; + } + } while (size >= chunksize); + } + else + { if (!content->next) + soap->dime.flags |= SOAP_DIME_ME; + if (soap_putdimehdr(soap)) + return soap->error; + do + { size_t bufsize; + if (size < sizeof(soap->tmpbuf)) + bufsize = size; + else + bufsize = sizeof(soap->tmpbuf); + if (!(bufsize = soap->fdimeread(soap, handle, soap->tmpbuf, bufsize))) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)soap->dime.size)); + soap->error = SOAP_EOF; + break; + } + if (soap_send_raw(soap, soap->tmpbuf, bufsize)) + break; + size -= bufsize; + } while (size); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n")); + soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3); + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n")); + if (soap->fdimereadclose) + soap->fdimereadclose(soap, handle); + } + else + { if (!content->next) + soap->dime.flags |= SOAP_DIME_ME; + if (soap_putdimehdr(soap) + || soap_putdimefield(soap, (char*)content->ptr, content->size)) + return soap->error; + } + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static char * +soap_getdimefield(struct soap *soap, size_t n) +{ register soap_wchar c; + register int i; + register char *s; + char *p = NULL; + if (n) + { p = (char*)soap_malloc(soap, n + 1); + if (p) + { s = p; + for (i = n; i > 0; i--) + { if ((int)(c = soap_get1(soap)) == EOF) + { soap->error = SOAP_EOF; + return NULL; + } + *s++ = (char)c; + } + *s = '\0'; + if ((soap->error = soap_move(soap, -(long)n&3))) + return NULL; + } + else + soap->error = SOAP_EOM; + } + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getdimehdr(struct soap *soap) +{ register soap_wchar c; + register char *s; + register int i; + unsigned char tmp[12]; + size_t optlen, idlen, typelen; + if (!(soap->mode & SOAP_ENC_DIME)) + return soap->error = SOAP_DIME_END; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME header\n")); + if (soap->dime.buflen || soap->dime.chunksize) + { if (soap_move(soap, (long)(soap->dime.size - soap_tell(soap)))) + return soap->error = SOAP_EOF; + soap_unget(soap, soap_getchar(soap)); /* skip padding and get hdr */ + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... From chunked\n")); + return SOAP_OK; + } + s = (char*)tmp; + for (i = 12; i > 0; i--) + { if ((int)(c = soap_getchar(soap)) == EOF) + return soap->error = SOAP_EOF; + *s++ = (char)c; + } + if ((tmp[0] & 0xF8) != SOAP_DIME_VERSION) + return soap->error = SOAP_DIME_MISMATCH; + soap->dime.flags = (tmp[0] & 0x7) | (tmp[1] & 0xF0); + optlen = (tmp[2] << 8) | tmp[3]; + idlen = (tmp[4] << 8) | tmp[5]; + typelen = (tmp[6] << 8) | tmp[7]; + soap->dime.size = (tmp[8] << 24) | (tmp[9] << 16) | (tmp[10] << 8) | tmp[11]; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME size=%lu flags=0x%X\n", (unsigned long)soap->dime.size, soap->dime.flags)); + if (!(soap->dime.options = soap_getdimefield(soap, optlen)) && soap->error) + return soap->error; + if (!(soap->dime.id = soap_getdimefield(soap, idlen)) && soap->error) + return soap->error; + if (!(soap->dime.type = soap_getdimefield(soap, typelen)) && soap->error) + return soap->error; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME id=%s, type=%s, options=%s\n", soap->dime.id?soap->dime.id:"", soap->dime.type?soap->dime.type:"", soap->dime.options?soap->dime.options+4:"")); + if (soap->dime.flags & SOAP_DIME_ME) + soap->mode &= ~SOAP_ENC_DIME; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getdime(struct soap *soap) +{ struct soap_multipart *content; + if (soap_getdimehdr(soap)) + return soap->error; + if (soap->fdimewriteopen && ((soap->dime.ptr = (char*)soap->fdimewriteopen(soap, soap->dime.id, soap->dime.type, soap->dime.options)) || soap->error)) + { const char *id, *type, *options; + size_t size, n; + if (!soap->dime.ptr) + return soap->error; + id = soap->dime.id; + type = soap->dime.type; + options = soap->dime.options; + for (;;) + { size = soap->dime.size; + for (;;) + { n = soap->buflen - soap->bufidx; + if (size < n) + n = size; + if ((soap->error = soap->fdimewrite(soap, (void*)soap->dime.ptr, soap->buf + soap->bufidx, n))) + break; + size -= n; + if (!size) + { soap->bufidx += n; + break; + } + if (soap_recv(soap)) + { soap->error = SOAP_EOF; + goto end; + } + } + if (soap_move(soap, -(long)soap->dime.size&3)) + { soap->error = SOAP_EOF; + break; + } + if (!(soap->dime.flags & SOAP_DIME_CF)) + break; + if (soap_getdimehdr(soap)) + break; + } +end: + if (soap->fdimewriteclose) + soap->fdimewriteclose(soap, (void*)soap->dime.ptr); + soap->dime.size = 0; + soap->dime.id = id; + soap->dime.type = type; + soap->dime.options = options; + } + else if (soap->dime.flags & SOAP_DIME_CF) + { const char *id, *type, *options; + register soap_wchar c; + register char *s; + register int i; + id = soap->dime.id; + type = soap->dime.type; + options = soap->dime.options; + if (soap_new_block(soap)) + return SOAP_EOM; + for (;;) + { s = (char*)soap_push_block(soap, soap->dime.size); + if (!s) + return soap->error = SOAP_EOM; + for (i = soap->dime.size; i > 0; i--) + { if ((int)(c = soap_get1(soap)) == EOF) + return soap->error = SOAP_EOF; + *s++ = (char)c; + } + if (soap_move(soap, -(long)soap->dime.size&3)) + return soap->error = SOAP_EOF; + if (!(soap->dime.flags & SOAP_DIME_CF)) + break; + if (soap_getdimehdr(soap)) + return soap->error; + } + soap->dime.size = soap->blist->size++; /* allocate one more for '\0' */ + if (!(soap->dime.ptr = soap_save_block(soap, NULL, 0))) + return soap->error; + soap->dime.ptr[soap->dime.size] = '\0'; /* force 0-terminated */ + soap->dime.id = id; + soap->dime.type = type; + soap->dime.options = options; + } + else + soap->dime.ptr = soap_getdimefield(soap, soap->dime.size); + content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, soap->dime.ptr, soap->dime.size); + if (!content) + return soap->error = SOAP_EOM; + content->id = soap->dime.id; + content->type = soap->dime.type; + content->options = soap->dime.options; + return soap->error; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getmimehdr(struct soap *soap) +{ struct soap_multipart *content; + do + { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) + return soap->error; + } + while (!*soap->msgbuf); + if (soap->msgbuf[0] == '-' && soap->msgbuf[1] == '-') + { char *s = soap->msgbuf + strlen(soap->msgbuf) - 1; + /* remove white space */ + while (soap_blank(*s)) + s--; + s[1] = '\0'; + if (soap->mime.boundary) + { if (strcmp(soap->msgbuf + 2, soap->mime.boundary)) + return soap->error = SOAP_MIME_ERROR; + } + else + soap->mime.boundary = soap_strdup(soap, soap->msgbuf + 2); + if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) + return soap->error; + } + if (soap_set_mime_attachment(soap, NULL, 0, SOAP_MIME_NONE, NULL, NULL, NULL, NULL)) + return soap->error = SOAP_EOM; + content = soap->mime.last; + for (;;) + { register char *key = soap->msgbuf; + register char *val; + if (!*key) + break; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "MIME header: %s\n", key)); + val = strchr(soap->msgbuf, ':'); + if (val) + { *val = '\0'; + do val++; + while (*val && *val <= 32); + if (!soap_tag_cmp(key, "Content-ID")) + content->id = soap_strdup(soap, val); + else if (!soap_tag_cmp(key, "Content-Location")) + content->location = soap_strdup(soap, val); + else if (!soap_tag_cmp(key, "Content-Type")) + content->type = soap_strdup(soap, val); + else if (!soap_tag_cmp(key, "Content-Description")) + content->description = soap_strdup(soap, val); + else if (!soap_tag_cmp(key, "Content-Transfer-Encoding")) + content->encoding = (enum soap_mime_encoding)soap_int_code(mime_codes, val, (long)SOAP_MIME_NONE); + } + if (soap_getline(soap, key, sizeof(soap->msgbuf))) + return soap->error; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getmime(struct soap *soap) +{ register soap_wchar c; + if (!soap->mime.last) + return SOAP_OK; + for (;;) + { register size_t i, m = 0; + register char *s; + struct soap_multipart *content = soap->mime.last; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Parsing MIME content id=%s type=%s\n", content->id?content->id:"", content->type?content->type:"")); + if (soap_new_block(soap)) + return soap->error = SOAP_EOM; + for (;;) + { register char *t = NULL; + if (!(s = (char*)soap_push_block(soap, SOAP_BLKLEN))) + return soap->error = SOAP_EOM; + for (i = 0; i < SOAP_BLKLEN; i++) + { if (m > 0) + { *s++ = *t++; + m--; + } + else + { c = soap_get1(soap); + if ((int)c == EOF) + return soap->error = SOAP_EOF; + if (c == '\r') + { t = soap->tmpbuf; + strcpy(t, "\n--"); + strncat(t, soap->mime.boundary, sizeof(soap->tmpbuf)-3); + t[sizeof(soap->tmpbuf)-1] = '\0'; + do c = soap_getchar(soap); + while (c == *t++); + if ((int)c == EOF) + return soap->error = SOAP_EOF; + if (!*--t) + goto end; + *t = (char)c; + m = t - soap->tmpbuf + 1; + t = soap->tmpbuf; + c = '\r'; + } + *s++ = (char)c; + } + } + } +end: + *s = '\0'; /* force 0-terminated */ + content->size = soap_size_block(soap, i+1)-1; + content->ptr = soap_save_block(soap, NULL, 0); + if (c == '-' && soap_getchar(soap) == '-') + break; + while (c != '\r' && (int)c != EOF && soap_blank(c)) + c = soap_getchar(soap); + if (c != '\r' || soap_getchar(soap) != '\n') + return soap->error = SOAP_MIME_ERROR; + if (soap_getmimehdr(soap)) + return soap->error; + } + do c = soap_getchar(soap); + while ((int)c != EOF && c != '\r'); + if ((int)c == EOF) + return soap->error = SOAP_EOF; + if (soap_getchar(soap) != '\n') + return soap->error = SOAP_MIME_ERROR; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putmimehdr(struct soap *soap, struct soap_multipart *content) +{ const char *s; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "MIME attachment type=%s\n", content->type?content->type:"")); + if (soap_send3(soap, "\r\n--", soap->mime.boundary, "\r\n")) + return soap->error; + if (content->type && soap_send3(soap, "Content-Type: ", content->type, "\r\n")) + return soap->error; + s = soap_str_code(mime_codes, content->encoding); + if (s && soap_send3(soap, "Content-Transfer-Encoding: ", s, "\r\n")) + return soap->error; + if (content->id && soap_send3(soap, "Content-ID: ", content->id, "\r\n")) + return soap->error; + if (content->location && soap_send3(soap, "Content-Location: ", content->location, "\r\n")) + return soap->error; + if (content->description && soap_send3(soap, "Content-Description: ", content->description, "\r\n")) + return soap->error; + return soap_send_raw(soap, "\r\n", 2); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putmime(struct soap *soap) +{ struct soap_multipart *content; + if (!(soap->mode & SOAP_ENC_MIME) || !soap->mime.boundary) + return SOAP_OK; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending MIME attachments\n")); + for (content = soap->mime.first; content; content = content->next) + if (soap_putmimehdr(soap, content) + || soap_send_raw(soap, content->ptr, content->size)) + return soap->error; + return soap_send3(soap, "\r\n--", soap->mime.boundary, "--\r\n"); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_dime(struct soap *soap) +{ soap->omode |= SOAP_ENC_DIME; + soap->dime.first = NULL; + soap->dime.last = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_mime(struct soap *soap, const char *boundary, const char *start) +{ soap->omode |= SOAP_ENC_MIME; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = soap_strdup(soap, boundary); + soap->mime.start = soap_strdup(soap, start); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_clr_dime(struct soap *soap) +{ soap->omode &= ~SOAP_ENC_DIME; + soap->dime.first = NULL; + soap->dime.last = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_clr_mime(struct soap *soap) +{ soap->omode &= ~SOAP_ENC_MIME; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = NULL; + soap->mime.start = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static struct soap_multipart* +soap_new_multipart(struct soap *soap, struct soap_multipart **first, struct soap_multipart **last, char *ptr, size_t size) +{ struct soap_multipart *content; + content = (struct soap_multipart*)soap_malloc(soap, sizeof(struct soap_multipart)); + if (content) + { content->next = NULL; + content->ptr = ptr; + content->size = size; + content->id = NULL; + content->type = NULL; + content->options = NULL; + content->encoding = SOAP_MIME_NONE; + content->location = NULL; + content->description = NULL; + if (!*first) + *first = content; + if (*last) + (*last)->next = content; + *last = content; + } + return content; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_dime_attachment(struct soap *soap, char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option) +{ struct soap_multipart *content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, ptr, size); + if (!content) + return SOAP_EOM; + content->id = soap_strdup(soap, id); + content->type = soap_strdup(soap, type); + content->options = soap_dime_option(soap, optype, option); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_mime_attachment(struct soap *soap, char *ptr, size_t size, enum soap_mime_encoding encoding, const char *type, const char *id, const char *location, const char *description) +{ struct soap_multipart *content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, ptr, size); + if (!content) + return SOAP_EOM; + content->id = soap_strdup(soap, id); + content->type = soap_strdup(soap, type); + content->encoding = encoding; + content->location = soap_strdup(soap, location); + content->description = soap_strdup(soap, description); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +struct soap_multipart* +SOAP_FMAC2 +soap_next_multipart(struct soap_multipart *content) +{ if (content) + return content->next; + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static void +soap_select_mime_boundary(struct soap *soap) +{ while (!soap->mime.boundary || soap_valid_mime_boundary(soap)) + { register char *s = soap->mime.boundary; + register size_t n = 0; + if (s) + n = strlen(s); + if (n < 16) + { n = 72; + s = soap->mime.boundary = (char*)soap_malloc(soap, n); + if (!s) + return; + } + strcpy(s, "<>"); + s += 2; + n -= 4; + while (n) + { *s++ = soap_base64o[rand()&0x3F]; + n--; + } + *s = '\0'; + strcat(s, "<>"); + } + if (!soap->mime.start) + soap->mime.start = ""; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static int +soap_valid_mime_boundary(struct soap *soap) +{ register struct soap_multipart *content; + register size_t k = strlen(soap->mime.boundary); + for (content = soap->mime.first; content; content = content->next) + { if (content->ptr && content->size >= k) + { register const char *p = (const char*)content->ptr; + register size_t i; + for (i = 0; i < content->size - k; i++, p++) + if (!strncmp(p, soap->mime.boundary, k)) + return SOAP_ERR; + } + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ + +#ifdef WITH_COOKIES +/******************************************************************************/ +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_encode_cookie(const char *s, char *t, size_t len) +{ register int c; + register size_t n = len; + while ((c = *s++) && --n > 0) + { if (c > ' ' && c < 128 && c != ';' && c != ',') + *t++ = c; + else if (n > 2) + { *t++ = '%'; + *t++ = (c >> 4) + (c > 159 ? '7' : '0'); + c &= 0xF; + *t++ = c + (c > 9 ? '7' : '0'); + n -= 2; + } + else + break; + } + *t = '\0'; + return len - n; +} + +/******************************************************************************/ +SOAP_FMAC1 +struct soap_cookie* +SOAP_FMAC2 +soap_cookie(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + size_t n; + if (!domain) + domain = soap->cookie_domain; + if (!path) + path = soap->cookie_path; + if (*path == '/') + path++; + n = strlen(path); + for (p = soap->cookies; p; p = p->next) + if (!strcmp(p->name, name) + && domain + && p->domain + && !strcmp(p->domain, domain) + && !strncmp(p->path, path, n)) + break; + return p; +} + +/******************************************************************************/ +SOAP_FMAC1 +struct soap_cookie* +SOAP_FMAC2 +soap_set_cookie(struct soap *soap, const char *name, const char *value, const char *domain, const char *path) +{ struct soap_cookie **p, *q; + int n; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set cookie: %s=%s domain=%s path=%s\n", name, value?value:"", domain?domain:"", path?path:"")); + if (!domain) + domain = soap->cookie_domain; + if (!path) + path = soap->cookie_path; + if (!path) + { soap_set_receiver_error(soap, "Cookie path not set", NULL, SOAP_HTTP_ERROR); + return NULL; + } + if (*path == '/') + path++; + q = soap_cookie(soap, name, domain, path); + if (!q) + { if ((q = (struct soap_cookie*)SOAP_MALLOC(sizeof(struct soap_cookie)))) + { if ((q->name = (char*)SOAP_MALLOC(strlen(name)+1))) + strcpy(q->name, name); + q->value = NULL; + q->domain = NULL; + q->path = NULL; + q->expire = -1; + q->version = 0; + q->secure = 0; + q->env = 0; + q->modified = 0; + for (p = &soap->cookies, n = soap->cookie_max; *p && n; p = &(*p)->next, n--) + if (!strcmp((*p)->name, name) && (*p)->path && strcmp((*p)->path, path) < 0) + break; + if (n) + { q->next = *p; + *p = q; + } + else + { SOAP_FREE(q->name); + SOAP_FREE(q); + q = NULL; + } + } + } + else + q->modified = 1; + if (q) + { if (q->value) + { SOAP_FREE(q->value); + q->value = NULL; + } + if (q->domain) + { SOAP_FREE(q->domain); + q->domain = NULL; + } + if (q->path) + { SOAP_FREE(q->path); + q->path = NULL; + } + if (value && *value && (q->value = (char*)SOAP_MALLOC(strlen(value)+1))) + strcpy(q->value, value); + if (domain && *domain && (q->domain = (char*)SOAP_MALLOC(strlen(domain)+1))) + strcpy(q->domain, domain); + if (path && *path && (q->path = (char*)SOAP_MALLOC(strlen(path)+1))) + strcpy(q->path, path); + q->session = 1; + } + return q; +} + +/******************************************************************************/ +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_clr_cookie(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie **p, *q; + if (!domain) + domain = soap->cookie_domain; + if (!domain) + { soap_set_receiver_error(soap, "Cookie domain not set", SOAP_STR_EOS, SOAP_HTTP_ERROR); + return; + } + if (!path) + path = soap->cookie_path; + if (!path) + { soap_set_receiver_error(soap, "Cookie path not set", SOAP_STR_EOS, SOAP_HTTP_ERROR); + return; + } + if (*path == '/') + path++; + for (p = &soap->cookies, q = *p; q; q = *p) + if (!strcmp(q->name, name) && !strcmp(q->domain, domain) && !strncmp(q->path, path, strlen(q->path))) + { if (q->value) + SOAP_FREE(q->value); + if (q->domain) + SOAP_FREE(q->domain); + if (q->path) + SOAP_FREE(q->path); + *p = q->next; + SOAP_FREE(q); + } + else + p = &q->next; +} + +/******************************************************************************/ +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + return p->value; + return NULL; +} + +/******************************************************************************/ +SOAP_FMAC1 +long +SOAP_FMAC2 +soap_cookie_expire(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + return p->expire; + return -1; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_cookie_expire(struct soap *soap, const char *name, long expire, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + { p->expire = expire; + p->modified = 1; + return SOAP_OK; + } + return SOAP_ERR; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + { p->session = 1; + p->modified = 1; + return SOAP_OK; + } + return SOAP_ERR; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_clr_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + { p->session = 0; + p->modified = 1; + return SOAP_OK; + } + return SOAP_ERR; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putsetcookies(struct soap *soap) +{ struct soap_cookie *p; + char *s, tmp[4096]; + const char *t; + for (p = soap->cookies; p; p = p->next) + { if (p->modified || !p->env) + { s = tmp; + if (p->name) + s += soap_encode_cookie(p->name, s, tmp-s+4064); + if (p->value && *p->value) + { *s++ = '='; + s += soap_encode_cookie(p->value, s, tmp-s+4064); + } + if (p->domain && (int)strlen(p->domain) < tmp-s+4064) + sprintf(s, ";Domain=%s", p->domain); + else if (soap->cookie_domain && (int)strlen(soap->cookie_domain) < tmp-s+4064) + sprintf(s, ";Domain=%s", soap->cookie_domain); + strcat(s, ";Path=/"); + if (p->path) + t = p->path; + else + t = soap->cookie_path; + if (t) + { if (*t == '/') + t++; + if ((int)strlen(t) < tmp-s+4064) + strcat(s, t); + } + s += strlen(s); + if (p->version > 0) + sprintf(s, ";Version=%u", p->version); + if (p->expire >= 0) + sprintf(s, ";Max-Age=%ld", p->expire); + if (p->secure) + strcat(s, ";Secure"); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set-Cookie: %s\n", tmp)); + if (soap->fposthdr(soap, "Set-Cookie", tmp)) + return soap->error; + } + } + return SOAP_OK; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putcookies(struct soap *soap, const char *domain, const char *path, int secure) +{ struct soap_cookie **p, *q; + unsigned int version = 0; + time_t now = time(NULL); + char *s, tmp[4096]; + p = &soap->cookies; + while ((q = *p)) + { if (q->expire && now > q->expire) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie %s expired\n", q->name)); + SOAP_FREE(q->name); + if (q->value) + SOAP_FREE(q->value); + if (q->domain) + SOAP_FREE(q->domain); + if (q->path) + SOAP_FREE(q->path); + *p = q->next; + SOAP_FREE(q); + } + else if ((!q->domain || !strcmp(q->domain, domain)) + && (!q->path || !strncmp(q->path, path, strlen(q->path))) + && (!q->secure || secure)) + { s = tmp; + if (q->version != version) + { sprintf(s, "$Version=%u;", q->version); + version = q->version; + } + if (q->name) + s += soap_encode_cookie(q->name, s, tmp-s+4080); + if (q->value && *q->value) + { *s++ = '='; + s += soap_encode_cookie(q->value, s, tmp-s+4080); + } + if (q->path && (int)strlen(q->path) < tmp-s+4080) + { sprintf(s, ";$Path=/%s", q->path); + s += strlen(s); + } + if (q->domain && (int)strlen(q->domain) < tmp-s+4080) + sprintf(s, ";$Domain=%s", q->domain); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie: %s\n", tmp)); + if (soap->fposthdr(soap, "Cookie", tmp)) + return soap->error; + p = &q->next; + } + else + p = &q->next; + } + return SOAP_OK; +} + +/******************************************************************************/ +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_getcookies(struct soap *soap, const char *val) +{ struct soap_cookie *p = NULL, *q; + const char *s; + char *t, tmp[4096]; /* cookie size is up to 4096 bytes [RFC2109] */ + char *domain = NULL; + char *path = NULL; + unsigned int version = 0; + time_t now = time(NULL); + if (!val) + return; + s = val; + while (*s) + { s = soap_decode_key(tmp, sizeof(tmp), s); + if (!soap_tag_cmp(tmp, "$Version")) + { if ((s = soap_decode_val(tmp, sizeof(tmp), s))) + { if (p) + p->version = (int)atol(tmp); + else + version = (int)atol(tmp); + } + } + else if (!soap_tag_cmp(tmp, "$Path")) + { s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { if ((t = (char*)SOAP_MALLOC(strlen(tmp)+1))) + strcpy(t, tmp); + } + else + t = NULL; + if (p) + { if (p->path) + SOAP_FREE(p->path); + p->path = t; + } + else + { if (path) + SOAP_FREE(path); + path = t; + } + } + else if (!soap_tag_cmp(tmp, "$Domain")) + { s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { if ((t = (char*)SOAP_MALLOC(strlen(tmp)+1))) + strcpy(t, tmp); + } + else + t = NULL; + if (p) + { if (p->domain) + SOAP_FREE(p->domain); + p->domain = t; + } + else + { if (domain) + SOAP_FREE(domain); + domain = t; + } + } + else if (p && !soap_tag_cmp(tmp, "Path")) + { if (p->path) + SOAP_FREE(p->path); + s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { if ((p->path = (char*)SOAP_MALLOC(strlen(tmp)+1))) + strcpy(p->path, tmp); + } + else + p->path = NULL; + } + else if (p && !soap_tag_cmp(tmp, "Domain")) + { if (p->domain) + SOAP_FREE(p->domain); + s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { if ((p->domain = (char*)SOAP_MALLOC(strlen(tmp)+1))) + strcpy(p->domain, tmp); + } + else + p->domain = NULL; + } + else if (p && !soap_tag_cmp(tmp, "Version")) + { s = soap_decode_val(tmp, sizeof(tmp), s); + p->version = (unsigned int)atol(tmp); + } + else if (p && !soap_tag_cmp(tmp, "Max-Age")) + { s = soap_decode_val(tmp, sizeof(tmp), s); + p->expire = now + atol(tmp); + } + else if (p && !soap_tag_cmp(tmp, "Expires")) + { struct tm T; + char a[3]; + static const char mns[] = "anebarprayunulugepctovec"; + s = soap_decode_val(tmp, sizeof(tmp), s); + if (strlen(tmp) > 20) + { memset((void*)&T, 0, sizeof(T)); + a[0] = tmp[4]; + a[1] = tmp[5]; + a[2] = '\0'; + T.tm_mday = (int)atol(a); + a[0] = tmp[8]; + a[1] = tmp[9]; + T.tm_mon = (strstr(mns, a) - mns) / 2; + a[0] = tmp[11]; + a[1] = tmp[12]; + T.tm_year = 100 + (int)atol(a); + a[0] = tmp[13]; + a[1] = tmp[14]; + T.tm_hour = (int)atol(a); + a[0] = tmp[16]; + a[1] = tmp[17]; + T.tm_min = (int)atol(a); + a[0] = tmp[19]; + a[1] = tmp[20]; + T.tm_sec = (int)atol(a); + p->expire = soap_timegm(&T); + } + } + else if (p && !soap_tag_cmp(tmp, "Secure")) + p->secure = 1; + else + { if (p) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie %s=%s domain=%s path=%s expire=%ld secure=%d\n", p->name, p->value?p->value:"", p->domain?p->domain:"", p->path?p->path:"", p->expire, p->secure)); + if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path))) + { q->version = p->version; + q->expire = p->expire; + q->secure = p->secure; + q->env = 1; + } + if (p->name) + SOAP_FREE(p->name); + if (p->value) + SOAP_FREE(p->value); + if (p->domain) + SOAP_FREE(p->domain); + if (p->path) + SOAP_FREE(p->path); + SOAP_FREE(p); + } + if ((p = (struct soap_cookie*)SOAP_MALLOC(sizeof(struct soap_cookie)))) + { p->name = (char*)SOAP_MALLOC(strlen(tmp)+1); + strcpy(p->name, tmp); + s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { p->value = (char*)SOAP_MALLOC(strlen(tmp)+1); + strcpy(p->value, tmp); + } + else + p->value = NULL; + p->domain = domain; + p->path = path; + p->expire = 0; + p->secure = 0; + p->version = version; + } + } + } + if (p) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got cookie %s=%s domain=%s path=%s expire=%ld secure=%d\n", p->name, p->value?p->value:"", p->domain?p->domain:"", p->path?p->path:"", p->expire, p->secure)); + if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path))) + { q->version = p->version; + q->expire = p->expire; + q->secure = p->secure; + } + if (p->name) + SOAP_FREE(p->name); + if (p->value) + SOAP_FREE(p->value); + if (p->domain) + SOAP_FREE(p->domain); + if (p->path) + SOAP_FREE(p->path); + SOAP_FREE(p); + } + if (domain) + SOAP_FREE(domain); + if (path) + SOAP_FREE(path); +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getenv_cookies(struct soap *soap) +{ struct soap_cookie *p; + const char *s; + char key[4096], val[4096]; /* cookie size is up to 4096 bytes [RFC2109] */ + if (!(s = getenv("HTTP_COOKIE"))) + return SOAP_ERR; + do + { s = soap_decode_key(key, sizeof(key), s); + s = soap_decode_val(val, sizeof(val), s); + p = soap_set_cookie(soap, key, val, NULL, NULL); + if (p) + p->env = 1; + } while (*s); + return SOAP_OK; +} + +/******************************************************************************/ +SOAP_FMAC1 +struct soap_cookie* +SOAP_FMAC2 +soap_copy_cookies(struct soap *soap) +{ struct soap_cookie *p, **q, *r; + q = &r; + for (p = soap->cookies; p; p = p->next) + { if (!(*q = (struct soap_cookie*)SOAP_MALLOC(sizeof(struct soap_cookie)))) + return r; + **q = *p; + if (p->name) + { if (((*q)->name = (char*)SOAP_MALLOC(strlen(p->name)+1))) + strcpy((*q)->name, p->name); + } + if (p->value) + { if (((*q)->value = (char*)SOAP_MALLOC(strlen(p->value)+1))) + strcpy((*q)->value, p->value); + } + if (p->domain) + { if (((*q)->domain = (char*)SOAP_MALLOC(strlen(p->domain)+1))) + strcpy((*q)->domain, p->domain); + } + if (p->path) + { if (((*q)->path = (char*)SOAP_MALLOC(strlen(p->path)+1))) + strcpy((*q)->path, p->path); + } + q = &(*q)->next; + } + *q = NULL; + return r; +} + +/******************************************************************************/ +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_free_cookies(struct soap *soap) +{ struct soap_cookie *p; + for (p = soap->cookies; p; p = soap->cookies) + { soap->cookies = p->next; + SOAP_FREE(p->name); + if (p->value) + SOAP_FREE(p->value); + if (p->domain) + SOAP_FREE(p->domain); + if (p->path) + SOAP_FREE(p->path); + SOAP_FREE(p); + } +} + +/******************************************************************************/ +#endif /* WITH_COOKIES */ + +/******************************************************************************/ +#ifdef WITH_GZIP +#ifndef PALM_1 +static int +soap_getgziphdr(struct soap *soap) +{ int i; + soap_wchar c, f = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get gzip header\n")); + for (i = 0; i < 9; i++) + { if ((int)(c = soap_get1(soap) == EOF)) + return soap->error = SOAP_EOF; + if (i == 2) + f = c; + } + if (f & 0x04) /* FEXTRA */ + { for (i = soap_get1(soap) | (soap_get1(soap) << 8); i; i--) + if ((int)soap_get1(soap) == EOF) + return soap->error = SOAP_EOF; + } + if (f & 0x08) /* FNAME */ + do + c = soap_get1(soap); + while (c && (int)c != EOF); + if ((int)c != EOF && (f & 0x10)) /* FCOMMENT */ + do + c = soap_get1(soap); + while (c && (int)f != EOF); + if ((int)c != EOF && (f & 0x01)) /* FHCRC */ + { if ((int)(c = soap_get1(soap)) != EOF) + c = soap_get1(soap); + } + if ((int)c == EOF) + return soap->error = SOAP_EOF; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_begin_recv(struct soap *soap) +{ soap_wchar c; + soap->error = SOAP_OK; + soap_free(soap); + soap_set_local_namespaces(soap); + soap->version = 0; /* don't assume we're parsing SOAP content by default */ + soap_free_iht(soap); + if ((soap->imode & SOAP_IO) == SOAP_IO_CHUNK) + soap->omode |= SOAP_IO_CHUNK; + soap->imode &= ~SOAP_IO; + soap->mode = soap->imode; + if (!soap->keep_alive) + { soap->buflen = 0; + soap->bufidx = 0; + } + if (!(soap->mode & SOAP_IO_KEEPALIVE)) + soap->keep_alive = 0; + soap->ahead = 0; + soap->peeked = 0; + soap->level = 0; + soap->part = SOAP_BEGIN; + soap->alloced = 0; + soap->count = 0; + soap->length = 0; + soap->cdata = 0; + *soap->endpoint = '\0'; + soap->userid = NULL; + soap->passwd = NULL; + soap->action = NULL; + soap->authrealm = NULL; + soap->dime.chunksize = 0; + soap->dime.buflen = 0; + soap->dime.list = NULL; + soap->dime.first = NULL; + soap->dime.last = NULL; + soap->mime.list = NULL; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = NULL; + soap->mime.start = NULL; +#ifdef WIN32 +#ifndef UNDER_CE +#ifndef WITH_FASTCGI + if (!soap_valid_socket(soap->socket)) +#ifdef __BORLANDC__ + setmode((SOAP_SOCKET)soap->recvfd, O_BINARY); +#else + _setmode((SOAP_SOCKET)soap->recvfd, _O_BINARY); +#endif +#endif +#endif +#endif +#ifdef WITH_ZLIB + soap->mode &= ~SOAP_ENC_ZLIB; + soap->zlib_in = SOAP_ZLIB_NONE; + soap->zlib_out = SOAP_ZLIB_NONE; + soap->d_stream.next_in = Z_NULL; + soap->d_stream.avail_in = 0; + soap->d_stream.next_out = (Byte*)soap->buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + soap->z_ratio_in = 1.0; + if (soap->fprepareinit) + soap->fprepareinit(soap); +#endif + c = soap_getchar(soap); +#ifdef WITH_GZIP + if (c == 0x1F) + { if (soap_getgziphdr(soap)) + return soap->error; + if (inflateInit2(&soap->d_stream, -MAX_WBITS) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; + soap->zlib_state = SOAP_ZLIB_INFLATE; + soap->mode |= SOAP_ENC_ZLIB; + soap->zlib_in = SOAP_ZLIB_GZIP; + soap->z_crc = crc32(0L, NULL, 0); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n")); + memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); + /* should not chunk over plain transport, so why bother to check? */ + /* if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) */ + /* soap->z_buflen = soap->bufidx; */ + /* else */ + soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx); + soap->d_stream.avail_in = soap->buflen - soap->bufidx; + soap->z_buflen = soap->buflen; + soap->buflen = soap->bufidx; + c = soap_getchar(soap); + } +#endif + if (c == '-' && soap_get0(soap) == '-') + soap->mode |= SOAP_ENC_MIME; + else if ((c & 0xFFFC) == (SOAP_DIME_VERSION | SOAP_DIME_MB) && (soap_get0(soap) & 0xFFF0) == 0x20) + soap->mode |= SOAP_ENC_DIME; + else + { while (soap_blank(c)) + c = soap_getchar(soap); + } + if ((int)c == EOF) + return soap->error = SOAP_EOF; + soap_unget(soap, c); + if (c != '<' && !(soap->mode & (SOAP_ENC_DIME | SOAP_ENC_ZLIB))) + { soap->mode &= ~SOAP_IO; + if ((soap->error = soap->fparse(soap))) + { soap->keep_alive = 0; /* force close later */ + return soap->error; + } + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) + { soap->chunkbuflen = soap->buflen; + soap->buflen = soap->bufidx; + soap->chunksize = 0; + } + else if (soap->fpreparerecv && soap->buflen != soap->bufidx) + soap->fpreparerecv(soap, soap->buf + soap->bufidx, soap->buflen - soap->bufidx); +#ifdef WITH_ZLIB + if (soap->zlib_in) + { /* fparse should not use soap_unget to push back last char */ +#ifdef WITH_GZIP + c = soap_get1(soap); + if (c == 0x1F) + { if (soap_getgziphdr(soap)) + return soap->error; + if (inflateInit2(&soap->d_stream, -MAX_WBITS) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; + soap->zlib_state = SOAP_ZLIB_INFLATE; + soap->z_crc = crc32(0L, NULL, 0); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n")); + } + else + { soap_revget1(soap); +#else + { +#endif + if (inflateInit(&soap->d_stream) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; + soap->zlib_state = SOAP_ZLIB_INFLATE; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate initialized\n")); + } + soap->mode |= SOAP_ENC_ZLIB; + memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); + soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx); + soap->d_stream.avail_in = soap->buflen - soap->bufidx; + soap->z_buflen = soap->buflen; + soap->buflen = soap->bufidx; + } +#endif + } +#ifndef WITH_LEANER + if (soap->mode & SOAP_ENC_MIME) + { if (soap_getmimehdr(soap)) + return soap->error; + if (soap_get_header_attribute(soap, soap->mime.first->type, "application/dime")) + soap->mode |= SOAP_ENC_DIME; + } + if (soap->mode & SOAP_ENC_DIME) + { if (soap_getdimehdr(soap)) + return soap->error; + if (soap->dime.flags & SOAP_DIME_CF) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked DIME SOAP message\n")); + soap->dime.chunksize = soap->dime.size; + if (soap->buflen - soap->bufidx >= soap->dime.chunksize) + { soap->dime.buflen = soap->buflen; + soap->buflen = soap->bufidx + soap->dime.chunksize; + } + else + soap->dime.chunksize -= soap->buflen - soap->bufidx; + } + soap->count = soap->buflen - soap->bufidx; + } +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +http_parse(struct soap *soap) +{ char header[SOAP_HDRLEN], *s; + unsigned short g = 0, k; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Waiting for response...\n")); + *soap->endpoint = '\0'; + soap->length = 0; + do + { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) + return soap->error; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP status: %s\n", soap->msgbuf)); + for (;;) + { if (soap_getline(soap, header, SOAP_HDRLEN)) + return soap->error; + if (!*header) + break; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP header: %s\n", header)); + s = strchr(header, ':'); + if (s) + { *s = '\0'; + do s++; + while (*s && *s <= 32); + if ((soap->error = soap->fparsehdr(soap, header, s))) + return soap->error; + } + } + if ((s = strchr(soap->msgbuf, ' '))) + k = (unsigned short)soap_strtoul(s, NULL, 10); + else + k = 0; + } while (k == 100); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Finished HTTP header parsing\n")); + s = strstr(soap->msgbuf, "HTTP/"); + if (s && s[7] != '1') + { if (soap->keep_alive == 1) + soap->keep_alive = 0; + if (k == 0 && (soap->omode & SOAP_IO) == SOAP_IO_CHUNK) /* k == 0 for HTTP request */ + { soap->imode |= SOAP_IO_CHUNK; + soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE; + } + } + if (soap->keep_alive < 0) + soap->keep_alive = 1; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Keep alive connection = %d\n", soap->keep_alive)); + if (s && (((g = !strncmp(soap->msgbuf, "GET ", 4))) || !strncmp(soap->msgbuf, "POST ", 5))) + { size_t m = strlen(soap->endpoint); + size_t n = m + (s - soap->msgbuf) - 5 - (!g); + if (n >= sizeof(soap->endpoint)) + n = sizeof(soap->endpoint) - 1; + strncpy(soap->path, soap->msgbuf + 4 + (!g), n - m); + soap->path[n - m] = '\0'; + strcat(soap->endpoint, soap->path); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Target endpoint='%s'\n", soap->endpoint)); + if (g) + { soap->error = soap->fget(soap); + if (soap->error == SOAP_OK) + soap->error = SOAP_STOP; /* prevents further processing */ + return soap->error; + } + return SOAP_OK; + } + if (k == 0 || (k >= 200 && k <= 299) || k == 400 || k == 500) + return SOAP_OK; + return soap_set_receiver_error(soap, "HTTP error", soap->msgbuf, k); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +http_parse_header(struct soap *soap, const char *key, const char *val) +{ if (!soap_tag_cmp(key, "Host")) + { +#ifdef WITH_OPENSSL + if (soap->imode & SOAP_ENC_SSL) + strcpy(soap->endpoint, "https://"); + else +#endif + strcpy(soap->endpoint, "http://"); + strncat(soap->endpoint, val, sizeof(soap->endpoint) - 8); + soap->endpoint[sizeof(soap->endpoint) - 1] = '\0'; + } +#ifndef WITH_LEANER + else if (!soap_tag_cmp(key, "Content-Type")) + { if (soap_get_header_attribute(soap, val, "application/dime")) + soap->mode |= SOAP_ENC_DIME; + else if (soap_get_header_attribute(soap, val, "multipart/related")) + { soap->mime.boundary = soap_strdup(soap, soap_get_header_attribute(soap, val, "boundary")); + soap->mime.start = soap_strdup(soap, soap_get_header_attribute(soap, val, "start")); + soap->mode |= SOAP_ENC_MIME; + } + } +#endif + else if (!soap_tag_cmp(key, "Content-Length")) + soap->length = soap_strtoul(val, NULL, 10); + else if (!soap_tag_cmp(key, "Content-Encoding")) + { if (!soap_tag_cmp(val, "deflate")) +#ifdef WITH_ZLIB + soap->zlib_in = SOAP_ZLIB_DEFLATE; +#else + return SOAP_ZLIB_ERROR; +#endif + else if (!soap_tag_cmp(val, "gzip")) +#ifdef WITH_GZIP + soap->zlib_in = SOAP_ZLIB_GZIP; +#else + return SOAP_ZLIB_ERROR; +#endif + } +#ifdef WITH_ZLIB + else if (!soap_tag_cmp(key, "Accept-Encoding")) + { +#ifdef WITH_GZIP + if (strchr(val, '*') || soap_get_header_attribute(soap, val, "gzip")) + soap->zlib_out = SOAP_ZLIB_GZIP; + else +#endif + if (strchr(val, '*') || soap_get_header_attribute(soap, val, "deflate")) + soap->zlib_out = SOAP_ZLIB_DEFLATE; + else + soap->zlib_out = SOAP_ZLIB_NONE; + } +#endif + else if (!soap_tag_cmp(key, "Transfer-Encoding")) + { soap->mode &= ~SOAP_IO; + if (!soap_tag_cmp(val, "chunked")) + soap->mode |= SOAP_IO_CHUNK; + } + else if (!soap_tag_cmp(key, "Connection")) + { if (!soap_tag_cmp(val, "keep-alive")) + soap->keep_alive = -soap->keep_alive; + else if (!soap_tag_cmp(val, "close")) + soap->keep_alive = 0; + } +#ifndef WITH_LEAN + else if (!soap_tag_cmp(key, "Authorization")) + { if (!soap_tag_cmp(val, "Basic *")) + { size_t n; + char *s; + soap_base642s(soap, val + 6, soap->tmpbuf, sizeof(soap->tmpbuf) - 1, &n); + soap->tmpbuf[n] = '\0'; + if ((s = strchr(soap->tmpbuf, ':'))) + { *s = '\0'; + soap->userid = soap_strdup(soap, soap->tmpbuf); + soap->passwd = soap_strdup(soap, s + 1); + } + } + } + else if (!soap_tag_cmp(key, "WWW-Authenticate")) + soap->authrealm = soap_strdup(soap, soap_get_header_attribute(soap, val+6, "realm")); + else if (!soap_tag_cmp(key, "Expect")) + { if (!soap_tag_cmp(val, "100-continue")) + { if ((soap->error = soap->fposthdr(soap, "HTTP/1.1 100 Continue", NULL)) + || (soap->error = soap->fposthdr(soap, NULL, NULL))) + return soap->error; + } + } +#endif + else if (!soap_tag_cmp(key, "SOAPAction")) + { if (val[0] && val[1]) + { soap->action = soap_strdup(soap, val + 1); + soap->action[strlen(soap->action) - 1] = '\0'; + } + } + else if (!soap_tag_cmp(key, "Location")) + { strncpy(soap->endpoint, val, sizeof(soap->endpoint)); + soap->endpoint[sizeof(soap->endpoint) - 1] = '\0'; + } +#ifdef WITH_COOKIES + else if (!soap_tag_cmp(key, "Cookie") || !soap_tag_cmp(key, "Set-Cookie")) + soap_getcookies(soap, val); +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_get_header_attribute(struct soap *soap, const char *line, const char *key) +{ register const char *s = line; + if (s) + { while (*s) + { register short flag; + s = soap_decode_key(soap->tmpbuf, sizeof(soap->tmpbuf), s); + flag = soap_tag_cmp(soap->tmpbuf, key); + s = soap_decode_val(soap->tmpbuf, sizeof(soap->tmpbuf), s); + if (!flag) + return soap->tmpbuf; + } + } + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_decode_key(char *buf, size_t len, const char *val) +{ return soap_decode(buf, len, val, "=,;"); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_decode_val(char *buf, size_t len, const char *val) +{ if (*val != '=') + { *buf = '\0'; + return val; + } + return soap_decode(buf, len, val + 1, ",;"); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static const char* +soap_decode(char *buf, size_t len, const char *val, const char *sep) +{ const char *s; + char *t = buf; + for (s = val; *s; s++) + if (*s != ' ' && *s != '\t' && !strchr(sep, *s)) + break; + if (*s == '"') + { s++; + while (*s && *s != '"' && --len) + *t++ = *s++; + } + else + { while (soap_notblank(*s) && !strchr(sep, *s) && --len) + { if (*s == '%') + { *t++ = ((s[1] >= 'A' ? (s[1] & 0x7) + 9 : s[1] - '0') << 4) + + (s[2] >= 'A' ? (s[2] & 0x7) + 9 : s[2] - '0'); + s += 3; + } + else + *t++ = *s++; + } + } + *t = '\0'; + while (*s && !strchr(sep, *s)) + s++; + return s; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_envelope_begin_out(struct soap *soap) +{ +#ifndef WITH_LEANER + size_t n = 0; + if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && soap->mime.start) + { const char *s; + if (soap->mode & SOAP_ENC_DIME) + s = "application/dime"; + else if (soap->version == 2) + s = "application/soap+xml; charset=utf-8"; + else + s = "text/xml; charset=utf-8"; + sprintf(soap->tmpbuf, "--%s\r\nContent-Type: %s\r\nContent-Transfer-Encoding: binary\r\nContent-ID: %s\r\n\r\n", soap->mime.boundary, s, soap->mime.start); + n = strlen(soap->tmpbuf); + if (soap_send_raw(soap, soap->tmpbuf, n)) + return soap->error; + } + if (soap->mode & SOAP_IO_LENGTH) + soap->dime.size = soap->count; /* DIME in MIME correction */ + if (!(soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME)) + { if (soap_putdimehdr(soap)) + return soap->error; + } +#endif + soap->part = SOAP_IN_ENVELOPE; + return soap_element_begin_out(soap, "SOAP-ENV:Envelope", 0, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_envelope_end_out(struct soap *soap) +{ if (soap_element_end_out(soap, "SOAP-ENV:Envelope")) + return soap->error; +#ifndef WITH_LEANER + if ((soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME)) + { soap->dime.size = soap->count - soap->dime.size; /* DIME in MIME correction */ + sprintf(soap->id, soap->dime_id_format, 0); + soap->dime.id = soap->id; + if (soap->local_namespaces) + { if (soap->local_namespaces[0].out) + soap->dime.type = (char*)soap->local_namespaces[0].out; + else + soap->dime.type = (char*)soap->local_namespaces[0].ns; + } + soap->dime.options = NULL; + soap->dime.flags = SOAP_DIME_MB | SOAP_DIME_ABSURI; + if (!soap->dime.first) + soap->dime.flags |= SOAP_DIME_ME; + soap->count += 12 + ((strlen(soap->dime.id)+3)&(~3)) + ((strlen(soap->dime.type)+3)&(~3)); + } + if (soap->mode & SOAP_ENC_DIME) + return soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3); +#endif + soap->part = SOAP_END_ENVELOPE; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_envelope_begin_in(struct soap *soap) +{ register struct Namespace *p; + soap->part = SOAP_IN_ENVELOPE; + if (soap_element_begin_in(soap, "SOAP-ENV:Envelope", 0)) + return soap->error = SOAP_VERSIONMISMATCH; + p = soap->local_namespaces; + if (p) + { const char *ns = p[0].out; + if (!ns) + ns = p[0].ns; + if (!strcmp(ns, soap_env1)) + { soap->version = 1; /* make sure we use SOAP 1.1 */ + if (p[1].out) + SOAP_FREE(p[1].out); + if ((p[1].out = (char*)SOAP_MALLOC(sizeof(soap_enc1)))) + strcpy(p[1].out, soap_enc1); + } + else if (!strcmp(ns, soap_env2)) + { soap->version = 2; /* make sure we use SOAP 1.2 */ + if (p[1].out) + SOAP_FREE(p[1].out); + if ((p[1].out = (char*)SOAP_MALLOC(sizeof(soap_enc2)))) + strcpy(p[1].out, soap_enc2); + } + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_envelope_end_in(struct soap *soap) +{ if (soap_element_end_in(soap, "SOAP-ENV:Envelope")) + return soap->error; + soap->part = SOAP_END_ENVELOPE; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_body_begin_out(struct soap *soap) +{ soap->part = SOAP_IN_BODY; + if (soap->version == 1) + soap->encoding = 1; + if (soap_element(soap, "SOAP-ENV:Body", 0, NULL)) + return soap->error; + if ((soap->mode & SOAP_XML_SEC) && soap_attribute(soap, "id", "_0")) + return soap->error; + return soap_element_start_end_out(soap, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_body_end_out(struct soap *soap) +{ if (soap_element_end_out(soap, "SOAP-ENV:Body")) + return soap->error; + soap->part = SOAP_IN_BODY; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_body_begin_in(struct soap *soap) +{ soap->part = SOAP_IN_BODY; + return soap_element_begin_in(soap, "SOAP-ENV:Body", 0); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_body_end_in(struct soap *soap) +{ if (soap_element_end_in(soap, "SOAP-ENV:Body")) + return soap->error; + soap->part = SOAP_END_BODY; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv_header(struct soap *soap) +{ if (soap_getheader(soap) && soap->error == SOAP_TAG_MISMATCH) + soap->error = SOAP_OK; + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_endpoint(struct soap *soap, const char *endpoint) +{ register const char *s; + register size_t i, n; + *soap->endpoint = '\0'; + *soap->host = '\0'; + *soap->path = '\0'; + soap->port = 80; + if (!endpoint || !*endpoint) + return; +#ifdef WITH_OPENSSL + if (!strncmp(endpoint, "https:", 6)) + soap->port = 443; +#endif + strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint) - 1); + s = strchr(endpoint, ':'); + if (s && s[1] == '/' && s[2] == '/') + s += 3; + else + s = endpoint; + n = strlen(s); + if (n >= sizeof(soap->host)) + n = sizeof(soap->host) - 1; +/* WR[ */ +#ifdef WITH_IPV6 + if ('[' == s[0]) + { s++; + for (i = 0; i < n; i++) + { soap->host[i] = s[i]; + if (']' == s[i]) + { + s++; + break; + } + } + } + else + { for (i = 0; i < n; i++) + { soap->host[i] = s[i]; + if (s[i] == '/' || s[i] == ':') + break; + } + } +#else /* WITH_IPV6 */ +/* ]WR */ + for (i = 0; i < n; i++) + { soap->host[i] = s[i]; + if (s[i] == '/' || s[i] == ':') + break; + } +/* WR[ */ +#endif /* WITH_IPV6 */ +/* ]WR */ + soap->host[i] = '\0'; + if (s[i] == ':') + { soap->port = (int)atol(s + i + 1); + for (i++; i < n; i++) + if (s[i] == '/') + break; + } + if (s[i]) + { strncpy(soap->path, s + i + 1, sizeof(soap->path)); + soap->path[sizeof(soap->path) - 1] = '\0'; + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_connect(struct soap *soap, const char *endpoint, const char *action) +{ return soap_connect_command(soap, SOAP_POST, endpoint, action); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_connect_command(struct soap *soap, int http_command, const char *endpoint, const char *action) +{ char host[sizeof(soap->host)]; + int port; + size_t count; + soap->error = SOAP_OK; + strcpy(host, soap->host); /* save to compare */ + port = soap->port; /* save to compare */ + soap_set_endpoint(soap, endpoint); + if (action) + soap->action = soap_strdup(soap, action); + if (soap->fconnect) + { + if ((soap->error = soap->fconnect(soap, endpoint, soap->host, soap->port))) + return soap->error; + } + else if (*soap->host) + { soap->status = http_command; + if (!soap_valid_socket(soap->socket) || strcmp(soap->host, host) || soap->port != port) + { soap->keep_alive = 0; /* force close */ + soap_closesock(soap); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Connect to host='%s' path='%s' port=%d\n", soap->host, soap->path, soap->port)); + soap->socket = soap->fopen(soap, endpoint, soap->host, soap->port); + if (soap->error) + return soap->error; + soap->keep_alive = ((soap->omode & SOAP_IO_KEEPALIVE) != 0); + } + else if (!soap->keep_alive || !soap->fpoll || soap->fpoll(soap)) + { soap->keep_alive = 0; /* force close */ + soap_closesock(soap); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reconnect to host='%s' path='%s' port=%d\n", soap->host, soap->path, soap->port)); + soap->socket = soap->fopen(soap, endpoint, soap->host, soap->port); + if (soap->error) + return soap->error; + } + } + if (soap_begin_send(soap)) + return soap->error; + count = soap_count_attachments(soap); + if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML) && endpoint) + { unsigned int k = soap->mode; + soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB); + if ((k & SOAP_IO) != SOAP_IO_FLUSH) + soap->mode |= SOAP_IO_BUFFER; + if ((soap->error = soap->fpost(soap, endpoint, soap->host, soap->port, soap->path, action, count))) + return soap->error; + if ((k & SOAP_IO) == SOAP_IO_CHUNK) + { if (soap_flush(soap)) + return soap->error; + } + soap->mode = k; + } + if (http_command != SOAP_POST) + return soap_end_send(soap); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_s2base64(struct soap *soap, const unsigned char *s, char *t, size_t n) +{ register size_t i; + register unsigned long m; + register char *p; + if (!t) + t = (char*)soap_malloc(soap, (n + 2) / 3 * 4 + 1); + if (!t) + { soap->error = SOAP_EOM; + return NULL; + } + p = t; + t[0] = '\0'; + if (!s) + return p; + for (; n > 2; n -= 3, s += 3) + { m = s[0]; + m = (m << 8) | s[1]; + m = (m << 8) | s[2]; + for (i = 4; i > 0; m >>= 6) + t[--i] = soap_base64o[m & 0x3F]; + t += 4; + } + t[0] = '\0'; + if (n > 0) + { m = 0; + for (i = 0; i < n; i++) + m = (m << 8) | *s++; + for (; i < 3; i++) + m <<= 8; + for (i++; i > 0; m >>= 6) + t[--i] = soap_base64o[m & 0x3F]; + for (i = 3; i > n; i--) + t[i] = '='; + t[4] = '\0'; + } + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_base642s(struct soap *soap, const char *s, char *t, size_t l, size_t *n) +{ register int i, j, c; + register unsigned long m; + char *p = t; + if (n) + *n = 0; + for (;;) + { for (i = 0; i < SOAP_BLKLEN; i++) + { m = 0; + j = 0; + while (j < 4) + { c = *s++; + if (c == '=' || !c) + { i *= 3; + switch (j) + { case 2: + *t++ = (char)((m >> 4) & 0xFF); + i++; + break; + case 3: + *t++ = (char)((m >> 10) & 0xFF); + *t++ = (char)((m >> 2) & 0xFF); + i += 2; + } + if (n) + *n += i; + return p; + } + c -= '+'; + if (c >= 0 && c <= 79) + { m = (m << 6) + soap_base64i[c]; + j++; + } + } + *t++ = (char)((m >> 16) & 0xFF); + *t++ = (char)((m >> 8) & 0xFF); + *t++ = (char)(m & 0xFF); + if (l < 3) + { if (n) + *n += i; + return p; + } + l -= 3; + } + if (n) + *n += 3 * SOAP_BLKLEN; + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_puthttphdr(struct soap *soap, int status, size_t count) +{ register const char *s; + register int err; + if (status == SOAP_FILE) + s = soap->http_content; + else if (status == SOAP_HTML) + s = "text/html; charset=utf-8"; +#ifndef WITH_LEANER + else if (soap->mode & SOAP_ENC_DIME) + s = "application/dime"; +#endif + else if (soap->version == 2) + s = "application/soap+xml; charset=utf-8"; + else + s = "text/xml; charset=utf-8"; +#ifndef WITH_LEANER + if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && soap->mime.start && soap->status != SOAP_GET) + { sprintf(soap->tmpbuf, "multipart/related; boundary=\"%s\"; type=%s; start=\"%s\"", soap->mime.boundary, s, soap->mime.start); + s = soap->tmpbuf; + } +#endif + if ((err = soap->fposthdr(soap, "Content-Type", s))) + return err; +#ifdef WITH_ZLIB + if (soap->omode & SOAP_ENC_ZLIB) + { +#ifdef WITH_GZIP + err = soap->fposthdr(soap, "Content-Encoding", "gzip"); +#else + err = soap->fposthdr(soap, "Content-Encoding", "deflate"); +#endif + if (err) + return err; + } +#endif + if ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK) + err = soap->fposthdr(soap, "Transfer-Encoding", "chunked"); + else if (count > 0) + { sprintf(soap->tmpbuf, "%lu", (unsigned long)count); + err = soap->fposthdr(soap, "Content-Length", soap->tmpbuf); + } + if (err) + return err; + return soap->fposthdr(soap, "Connection", soap->keep_alive ? "keep-alive" : "close"); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +http_get(struct soap *soap) +{ return SOAP_GET_METHOD; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +http_post(struct soap *soap, const char *endpoint, const char *host, int port, const char *path, const char *action, size_t count) +{ register const char *s; + register int err; + if (soap->status == SOAP_GET) + { s = "GET"; + count = 0; + } + else + s = "POST"; +#ifdef PALM + if (!endpoint || (strncmp(endpoint, "http:", 5) && strncmp(endpoint, "https:", 6) && strncmp(endpoint, "httpg:", 6)) && strncmp(endpoint, "_beam:", 6) && strncmp(endpoint, "_local:", 7) && strncmp(endpoint, "_btobex:", 8)) +#else + if (!endpoint || (strncmp(endpoint, "http:", 5) && strncmp(endpoint, "https:", 6) && strncmp(endpoint, "httpg:", 6))) +#endif + return SOAP_OK; + if (soap->proxy_host && strncmp(endpoint, "https:", 6)) + sprintf(soap->tmpbuf, "%s %s HTTP/%s", s, endpoint, soap->http_version); + else + sprintf(soap->tmpbuf, "%s /%s HTTP/%s", s, path, soap->http_version); + if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return err; + if (port != 80) + sprintf(soap->tmpbuf, "%s:%d", host, port); + else + strcpy(soap->tmpbuf, host); + if ((err = soap->fposthdr(soap, "Host", soap->tmpbuf)) + || (err = soap->fposthdr(soap, "User-Agent", "gSOAP/2.7")) + || (err = soap_puthttphdr(soap, SOAP_OK, count))) + return err; +#ifdef WITH_ZLIB +#ifdef WITH_GZIP + if ((err = soap->fposthdr(soap, "Accept-Encoding", "gzip, deflate"))) +#else + if ((err = soap->fposthdr(soap, "Accept-Encoding", "deflate"))) +#endif + return err; +#endif +#ifndef WITH_LEAN + if (soap->userid && soap->passwd && strlen(soap->userid) + strlen(soap->passwd) < 761) + { sprintf(soap->tmpbuf + 262, "%s:%s", soap->userid, soap->passwd); + strcpy(soap->tmpbuf, "Basic "); + soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, strlen(soap->tmpbuf + 262)); + if ((err = soap->fposthdr(soap, "Authorization", soap->tmpbuf))) + return err; + } + if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761) + { sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd); + strcpy(soap->tmpbuf, "Basic "); + soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, strlen(soap->tmpbuf + 262)); + if ((err = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf))) + return err; + } +#endif +#ifdef WITH_COOKIES +#ifdef WITH_OPENSSL + if (soap_putcookies(soap, host, path, soap->ssl != NULL)) + return soap->error; +#else + if (soap_putcookies(soap, host, path, 0)) + return soap->error; +#endif +#endif + if (action && soap->version == 1) + { sprintf(soap->tmpbuf, "\"%s\"", action); + if ((err = soap->fposthdr(soap, "SOAPAction", soap->tmpbuf))) + return err; + } + return soap->fposthdr(soap, NULL, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +http_send_header(struct soap *soap, const char *s) +{ register const char *t; + do + { t = strchr(s, '\n'); /* disallow \n in HTTP headers */ + if (!t) + t = s + strlen(s); + if (soap_send_raw(soap, s, t - s)) + return soap->error; + s = t + 1; + } while (*t); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +http_post_header(struct soap *soap, const char *key, const char *val) +{ if (key) + { if (http_send_header(soap, key)) + return soap->error; + if (val && (soap_send_raw(soap, ": ", 2) || http_send_header(soap, val))) + return soap->error; + } + return soap_send_raw(soap, "\r\n", 2); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +http_response(struct soap *soap, int status, size_t count) +{ register int err; +/* WR[ */ +#ifdef WMW_RPM_IO + if (soap->rpmreqid) + httpOutputEnable(soap->rpmreqid); +#endif /* WMW_RPM_IO */ +/* ]WR */ + if (!status || status == SOAP_HTML || status == SOAP_FILE) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "OK 200\n")); +/* WR[ */ +#ifdef WMW_RPM_IO + if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */ +#else +/* ]WR */ + if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application */ +/* WR[ */ +#endif /* WMW_RPM_IO */ +/* ]WR */ + { sprintf(soap->tmpbuf, "HTTP/%s 200 OK", soap->http_version); + if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return err; + } + else if ((err = soap->fposthdr(soap, "Status", "200 OK"))) + return err; + } + else if (status > 200 && status < 600) + { sprintf(soap->tmpbuf, "HTTP/%s %d %s", soap->http_version, status, http_error(soap, status)); + if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return err; + if (status == 401) + { sprintf(soap->tmpbuf, "Basic realm=\"%s\"", soap->authrealm ? soap->authrealm : "gSOAP Web Service"); + if ((err = soap->fposthdr(soap, "WWW-Authenticate", soap->tmpbuf))) + return err; + } + else if ((status >= 301 && status <= 303) || status == 307) + { if ((err = soap->fposthdr(soap, "Location", soap->endpoint))) + return err; + } + } + else + { const char *s = *soap_faultcode(soap); + if (soap->version == 2 && !strcmp(s, "SOAP-ENV:Sender")) + s = "400 Bad Request"; + else + s = "500 Internal Server Error"; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error %s (status=%d)\n", s, status)); +/* WR[ */ +#ifdef WMW_RPM_IO + if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */ +#else +/* ]WR */ + if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application */ +/* WR[ */ +#endif /* WMW_RPM_IO */ +/* ]WR */ + { sprintf(soap->tmpbuf, "HTTP/%s %s", soap->http_version, s); + if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return err; + } + else if ((err = soap->fposthdr(soap, "Status", s))) + return err; + } + if ((err = soap->fposthdr(soap, "Server", "gSOAP/2.7")) + || (err = soap_puthttphdr(soap, status, count))) + return err; +#ifdef WITH_COOKIES + if (soap_putsetcookies(soap)) + return soap->error; +#endif + return soap->fposthdr(soap, NULL, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_response(struct soap *soap, int status) +{ register size_t count; + if (!(soap->omode & (SOAP_ENC_XML | SOAP_IO_STORE /* this tests for chunking too */)) + && (status == SOAP_HTML || status == SOAP_FILE)) + { soap->omode &= ~SOAP_IO; + soap->omode |= SOAP_IO_STORE; + } + soap->status = status; + count = soap_count_attachments(soap); + if (soap_begin_send(soap)) + return soap->error; + if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML)) + { register int n = soap->mode; + soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB); + if ((n & SOAP_IO) != SOAP_IO_FLUSH) + soap->mode |= SOAP_IO_BUFFER; + if ((soap->error = soap->fresponse(soap, status, count))) + return soap->error; + if ((n & SOAP_IO) == SOAP_IO_CHUNK) + { if (soap_flush(soap)) + return soap->error; + } + soap->mode = n; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static const char* +soap_set_validation_fault(struct soap *soap, const char *s, const char *t) +{ sprintf(soap->msgbuf, "Validation constraint violation: %s%s in element <%s>", s, t?t:SOAP_STR_EOS, soap->tag); + return soap->msgbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_fault(struct soap *soap) +{ const char **c = soap_faultcode(soap); + const char **s = soap_faultstring(soap); + if (!*c) + { if (soap->version == 2) + *c = "SOAP-ENV:Sender"; + else + *c = "SOAP-ENV:Client"; + } + if (*s) + return; + switch (soap->error) + { +#ifndef WITH_LEAN + case SOAP_CLI_FAULT: + *s = "Client fault"; + break; + case SOAP_SVR_FAULT: + *s = "Server fault"; + break; + case SOAP_TAG_MISMATCH: + *s = soap_set_validation_fault(soap, "tag name or namespace mismatch", NULL); + break; + case SOAP_TAG_END: + *s = soap_set_validation_fault(soap, "incorrect end tag", NULL); + break; + case SOAP_TYPE: + *s = soap_set_validation_fault(soap, "data type mismatch ", soap->type); + break; + case SOAP_SYNTAX_ERROR: + *s = "Well-formedness constraint violation"; + break; + case SOAP_NO_TAG: + *s = "No XML element tag found"; + break; + case SOAP_MUSTUNDERSTAND: + *c = "SOAP-ENV:MustUnderstand"; + sprintf(soap->msgbuf, "The data in element '%s' must be understood but cannot be handled", soap->tag); + *s = soap->msgbuf; + break; + case SOAP_VERSIONMISMATCH: + *c = "SOAP-ENV:VersionMismatch"; + *s = "SOAP version mismatch or invalid SOAP message"; + break; + case SOAP_DATAENCODINGUNKNOWN: + *c = "SOAP-ENV:DataEncodingUnknown"; + *s = "Unsupported SOAP data encoding"; + break; + case SOAP_NAMESPACE: + *s = soap_set_validation_fault(soap, "namespace mismatch", NULL); + break; + case SOAP_FATAL_ERROR: + *s = "Fatal error"; + break; + case SOAP_NO_METHOD: + sprintf(soap->msgbuf, "Method '%s' not implemented: method name or namespace not recognized", soap->tag); + *s = soap->msgbuf; + break; + case SOAP_GET_METHOD: + *s = "HTTP GET method not implemented"; + break; + case SOAP_EOM: + *s = "Out of memory"; + break; + case SOAP_IOB: + *s = "Array index out of bounds"; + break; + case SOAP_NULL: + *s = soap_set_validation_fault(soap, "nil not allowed", NULL); + break; + case SOAP_MULTI_ID: + *s = soap_set_validation_fault(soap, "multiple definitions of id ", soap->id); + break; + case SOAP_MISSING_ID: + *s = soap_set_validation_fault(soap, "missing id for ref ", soap->id); + break; + case SOAP_HREF: + *s = soap_set_validation_fault(soap, "incompatible object ref ", soap->id); + break; + case SOAP_FAULT: + break; + case SOAP_TCP_ERROR: + *s = tcp_error(soap); + break; + case SOAP_HTTP_ERROR: + *s = "HTTP error"; + break; + case SOAP_SSL_ERROR: + *s = "SSL error"; + break; + case SOAP_PLUGIN_ERROR: + *s = "Plugin registry error"; + break; + case SOAP_DIME_MISMATCH: + *s = "DIME version/transmission error"; + break; + case SOAP_DIME_END: + *s = "End of DIME error"; + break; + case SOAP_DIME_ERROR: + *s = "DIME format error"; + break; + case SOAP_MIME_ERROR: + *s = "MIME format error"; + break; + case SOAP_ZLIB_ERROR: +#ifdef WITH_ZLIB + sprintf(soap->msgbuf, "Zlib/gzip error: '%s'", soap->d_stream.msg?soap->d_stream.msg:""); + *s = soap->msgbuf; +#else + *s = "Zlib not installed for required message (de)compression"; +#endif + break; + case SOAP_REQUIRED: + *s = soap_set_validation_fault(soap, "missing required attribute", NULL); + break; + case SOAP_PROHIBITED: + *s = soap_set_validation_fault(soap, "prohibited attribute present", NULL); + break; + case SOAP_OCCURS: + *s = soap_set_validation_fault(soap, "a min/maxOccurs violation was detected", NULL); + break; + case SOAP_LENGTH: + *s = soap_set_validation_fault(soap, "content length violation", NULL); + break; +#endif + case SOAP_EOF: + sprintf(soap->msgbuf, "End of file or no input: '%s'", soap_strerror(soap)); + *s = soap->msgbuf; + break; + default: + if (soap->error > 200 && soap->error < 600) + { sprintf(soap->msgbuf, "HTTP Error: '%s'", http_error(soap, soap->error)); + *s = soap->msgbuf; + } + else + { sprintf(soap->msgbuf, "Error code %d", soap->error); + *s = soap->msgbuf; + } + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send_fault(struct soap *soap) +{ register int status = soap->error; + if (status == SOAP_STOP) + return status; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Sending back fault struct for error code %d\n", soap->error)); + soap->keep_alive = 0; /* to terminate connection */ + soap_set_fault(soap); + if ((status != SOAP_EOF || (!soap->recv_timeout && !soap->send_timeout)) && (!soap->fpoll || soap->fpoll(soap) == SOAP_OK)) + { soap->error = SOAP_OK; + soap_serializeheader(soap); + soap_serializefault(soap); + soap_begin_count(soap); + if (soap->mode & SOAP_IO_LENGTH) + { soap_envelope_begin_out(soap); + soap_putheader(soap); + soap_body_begin_out(soap); + soap_putfault(soap); + soap_body_end_out(soap); + soap_envelope_end_out(soap); + } + if (soap_response(soap, status) + || soap_envelope_begin_out(soap) + || soap_putheader(soap) + || soap_body_begin_out(soap) + || soap_putfault(soap) + || soap_body_end_out(soap) + || soap_envelope_end_out(soap)) + return soap_closesock(soap); + soap_end_send(soap); + } + soap->error = status; + return soap_closesock(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv_fault(struct soap *soap) +{ register int status = soap->error; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Receiving SOAP Fault\n")); + soap->error = SOAP_OK; + if (soap_getfault(soap)) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Error: soap_get_soapfault() failed. Is this a SOAP message at all?\n")); + *soap_faultcode(soap) = (soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client"); + soap->error = status; + soap_set_fault(soap); + } + else + { register const char *s = *soap_faultcode(soap); + if (!soap_match_tag(soap, s, "SOAP-ENV:Server") || !soap_match_tag(soap, s, "SOAP-ENV:Receiver")) + status = SOAP_SVR_FAULT; + else if (!soap_match_tag(soap, s, "SOAP-ENV:Client") || !soap_match_tag(soap, s, "SOAP-ENV:Sender")) + status = SOAP_CLI_FAULT; + else if (!soap_match_tag(soap, s, "SOAP-ENV:MustUnderstand")) + status = SOAP_MUSTUNDERSTAND; + else if (!soap_match_tag(soap, s, "SOAP-ENV:VersionMismatch")) + status = SOAP_VERSIONMISMATCH; + else + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Fault code %s\n", s)); + status = SOAP_FAULT; + } + if (soap_body_end_in(soap) + || soap_envelope_end_in(soap) + || soap_end_recv(soap)) + return soap_closesock(soap); + soap->error = status; + } + return soap_closesock(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static const char* +soap_strerror(struct soap *soap) +{ int err = soap->errnum; + if (!err) + err = soap_errno; + if (err) + { +#ifndef UNDER_CE + return strerror(err); +#else + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0, (LPTSTR)&soap->werrorstr, sizeof(soap->werrorstr), NULL); + wcstombs(soap->errorstr, soap->werrorstr, sizeof(soap->errorstr)); + return soap->errorstr; +#endif + } + return "Operation interrupted or timed out"; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +static int +soap_set_error(struct soap *soap, const char *faultcode, const char *faultstring, const char *faultdetail, int soaperror) +{ *soap_faultcode(soap) = faultcode; + *soap_faultstring(soap) = faultstring; + if (faultdetail && *faultdetail) + { register const char **s = soap_faultdetail(soap); + if (s) + *s = faultdetail; + } + return soap->error = soaperror; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_sender_error(struct soap *soap, const char *faultstring, const char *faultdetail, int soaperror) +{ return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", faultstring, faultdetail, soaperror); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_receiver_error(struct soap *soap, const char *faultstring, const char *faultdetail, int soaperror) +{ return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", faultstring, faultdetail, soaperror); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +static int +soap_copy_fault(struct soap *soap, const char *faultcode, const char *faultstring, const char *faultdetail) +{ char *s = NULL, *t = NULL; + if (faultstring) + s = soap_strdup(soap, faultstring); + if (faultdetail) + t = soap_strdup(soap, faultdetail); + return soap_set_error(soap, faultcode, s, t, SOAP_FAULT); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_sender_fault(struct soap *soap, const char *faultstring, const char *faultdetail) +{ return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", faultstring, faultdetail); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_receiver_fault(struct soap *soap, const char *faultstring, const char *faultdetail) +{ return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", faultstring, faultdetail); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_print_fault(struct soap *soap, FILE *fd) +{ if (soap->error) + { const char **s; + if (!*soap_faultcode(soap)) + soap_set_fault(soap); + fprintf(fd, "SOAP FAULT: %s\n\"%s\"\n", *soap_faultcode(soap), *soap_faultstring(soap)); + s = soap_faultdetail(soap); + if (s && *s) + fprintf(fd, "Detail: %s\n", *s); + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_print_fault_location(struct soap *soap, FILE *fd) +{ +#ifndef WITH_LEAN + int c; + if (soap->error && soap->buflen > 0) + { if (soap->bufidx == 0) + soap->bufidx = 1; + c = soap->buf[soap->bufidx - 1]; + soap->buf[soap->bufidx - 1] = '\0'; + if (soap->buflen - soap->bufidx > 1024) + soap->buf[soap->bufidx + 1024] = '\0'; + else + soap->buf[soap->buflen - 1] = '\0'; + fprintf(fd, "%s%c\n** HERE **\n", soap->buf, c); + if (soap->bufidx < soap->buflen) + fprintf(fd, "%s\n", soap->buf + soap->bufidx); + } +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_register_plugin_arg(struct soap *soap, int (*fcreate)(struct soap*, struct soap_plugin*, void*), void *arg) +{ register struct soap_plugin *p; + register int r; + if (!(p = (struct soap_plugin*)SOAP_MALLOC(sizeof(struct soap_plugin)))) + return soap->error = SOAP_EOM; + p->id = NULL; + p->data = NULL; + p->fcopy = NULL; + p->fdelete = NULL; + r = fcreate(soap, p, arg); + if (!r && p->fdelete) + { p->next = soap->plugins; + soap->plugins = p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Registered '%s' plugin\n", p->id)); + return SOAP_OK; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not register plugin '%s': plugin returned error %d (or fdelete callback not set)\n", p->id?p->id:"?", r)); + SOAP_FREE(p); + return r; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static void * +fplugin(struct soap *soap, const char *id) +{ register struct soap_plugin *p; + for (p = soap->plugins; p; p = p->next) + if (p->id == id || !strcmp(p->id, id)) + return p->data; + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void * +SOAP_FMAC2 +soap_lookup_plugin(struct soap *soap, const char *id) +{ return soap->fplugin(soap, id); +} +#endif + +/******************************************************************************/ +#ifdef __cplusplus +} +#endif + diff --git a/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.0.h b/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.0.h new file mode 100644 index 0000000..ff1d52d --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.0.h @@ -0,0 +1,1764 @@ +/* + +stdsoap2.h 2.7.0d + +gSOAP runtime environment. + +gSOAP XML Web services tools +Copyright (C) 2000-2004, Robert van Engelen, Genivia, Inc., All Rights Reserved. + +Contributors: + +Wind River Systems, Inc., for the following additions (marked WR[...]) : + - vxWorks compatible + - Support for IPv6. + +-------------------------------------------------------------------------------- +gSOAP public license. + +The contents of this file are subject to the gSOAP Public License Version 1.3 +(the "License"); you may not use this file except in compliance with the +License. You may obtain a copy of the License at +http://www.cs.fsu.edu/~engelen/soaplicense.html +Software distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +for the specific language governing rights and limitations under the License. + +The Initial Developer of the Original Code is Robert A. van Engelen. +Copyright (C) 2000-2004, Robert van Engelen, Genivia, Inc., All Rights Reserved. +-------------------------------------------------------------------------------- +GPL license. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA + +Author contact information: +engelen@genivia.com / engelen@acm.org +-------------------------------------------------------------------------------- +*/ + +#ifdef WITH_SOAPDEFS_H +# include "soapdefs.h" /* include user-defined stuff */ +#endif + +#ifndef _THREAD_SAFE +# define _THREAD_SAFE +#endif + +#ifndef OPENSERVER +# ifndef _REENTRANT +# define _REENTRANT +# endif +#endif + +#ifndef SOAP_BEGIN_NAMESPACE +# define SOAP_BEGIN_NAMESPACE(name) +#endif + +#ifndef SOAP_END_NAMESPACE +# define SOAP_END_NAMESPACE(name) +#endif + +#ifndef SOAP_FMAC1 /* stdsoap2.h declaration macro */ +# define SOAP_FMAC1 +#endif + +#ifndef SOAP_FMAC2 /* stdsoap2.h declaration macro */ +# define SOAP_FMAC2 +#endif + +#ifndef SOAP_FMAC3 /* (de)serializer declaration macro */ +# define SOAP_FMAC3 +#endif + +#ifndef SOAP_FMAC4 /* (de)serializer declaration macro */ +# define SOAP_FMAC4 +#endif + +#ifndef SOAP_FMAC5 /* stub/skeleton declaration macro */ +# define SOAP_FMAC5 +#endif + +#ifndef SOAP_FMAC6 /* stub/skeleton declaration macro */ +# define SOAP_FMAC6 +#endif + +#ifndef SOAP_CMAC /* class declaration macro */ +# define SOAP_CMAC +#endif + +#ifndef SOAP_NMAC /* namespace table declaration macro */ +# define SOAP_NMAC +#endif + +#ifndef SOAP_SOURCE_STAMP +# define SOAP_SOURCE_STAMP(str) +#endif + +#ifdef WITH_LEANER +# ifndef WITH_LEAN +# define WITH_LEAN +# endif +#endif + +#ifdef WITH_LEAN +# ifdef WITH_COOKIES +# error "Cannot build WITH_LEAN code WITH_COOKIES enabled" +# endif +#endif + +#ifndef STDSOAP_H +#define STDSOAP_H + +#if defined(__vxworks) || defined(__VXWORKS__) +# define VXWORKS +#endif + +#ifdef _WIN32 +# ifndef WIN32 +# define WIN32 +# endif +#endif + +#ifdef UNDER_CE +# ifndef WIN32 +# define WIN32 +# endif +#endif + +#ifdef __BORLANDC__ +# ifdef __WIN32__ +# ifndef WIN32 +# define WIN32 +# endif +# endif +#endif + +#ifdef __CYGWIN__ +# ifndef CYGWIN +# define CYGWIN +# endif +#endif + +#ifdef __SYMBIAN32__ +# define SYMBIAN +# undef WIN32 +#endif + +#if defined(__palmos__) || defined(PALM_GCC) || defined(__PALMOS_TRAPS__) +# define PALM +#endif + +#ifdef __hpux +# define HP_UX +#endif + +#ifdef __alpha +# define TRU64 +#endif + +#ifdef __MVS__ +# define OS390 +#endif + +#ifdef _AIX +# define __socklen_t_defined +#endif + +#ifdef HAVE_CONFIG_H +# include "config.h" +#else +# if defined(UNDER_CE) +# define WITH_LEAN +# define HAVE_SSCANF +# elif defined(WIN32) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(CYGWIN) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(__APPLE__) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_TIMEGM +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(_AIXVERSION_431) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(HP_UX) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(FREEBSD) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_GETTIMEOFDAY +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(__VMS) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(__GLIBC__) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_TIMEGM +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# define HAVE_ISNAN +# elif defined(TRU64) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_GETTIMEOFDAY +# define HAVE_SYS_TIMEB_H +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define __USE_STD_IOSTREAM +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(MAC_CARBON) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GETHOSTBYNAME_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(PALM) +# define WITH_LEAN +# define HAVE_STRTOD /* strtod() is defined in palmFunctions.h */ +# include /* Needs to be included before unix headers */ +# include +# define IGNORE_STDIO_STUBS +# include +# define O_NONBLOCK FNONBIO +# include +# include +# include "palmFunctions.h" +# elif defined(SYMBIAN) +# define WITH_LEAN +# define WITH_NONAMESPACES +# define HAVE_STRTOD /* use STRTOD since sscanf doesn't seem to work */ +# include +# elif defined(VXWORKS) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_RAND_R +# define HAVE_PGMTIME_R +# define HAVE_PLOCALTIME_R +# define HAVE_MKTIME +# elif defined(OS390) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MB +# else +/* Default asumptions on supported functions */ +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GETHOSTBYNAME_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# endif +#endif + +#if defined(TRU64) +# define SOAP_LONG_FORMAT "%ld" +# define SOAP_ULONG_FORMAT "%lu" +#elif defined(WIN32) +# define SOAP_LONG_FORMAT "%I64d" +# define SOAP_ULONG_FORMAT "%I64u" +#endif + +#ifndef SOAP_LONG_FORMAT +# define SOAP_LONG_FORMAT "%lld" /* printf format for 64 bit ints */ +#endif + +#ifndef SOAP_ULONG_FORMAT +# define SOAP_ULONG_FORMAT "%llu" /* printf format for unsigned 64 bit ints */ +#endif + +#ifndef SOAP_MALLOC /* use libc malloc */ +# define SOAP_MALLOC(n) malloc(n) +#endif + +#ifndef SOAP_FREE /* use libc free */ +# define SOAP_FREE(p) free(p) +#endif + +#include + +#ifndef PALM +# include +# include +#endif + +#include +#include + +#if defined(__cplusplus) && !defined(WITH_LEAN) +# include +# include + using namespace std; +#endif + +#ifndef UNDER_CE +# ifndef PALM +# include +# ifndef MAC_CARBON +# include +# endif +# ifndef WITH_LEAN +# ifdef HAVE_SYS_TIMEB_H +# include /* for ftime() */ +# endif +# include +# endif +# endif +#endif + +#ifdef OPENSERVER +# include +# include +# include + extern int h_errno; +#endif + +#ifndef MAC_CARBON +# ifndef WIN32 +# ifndef PALM +# include +# ifdef VXWORKS +# include +# endif +# ifndef VXWORKS +# ifndef SYMBIAN +# include +# endif +# endif +# ifdef SUN_OS +# include /* SUN */ +# include /* SUN < 2.8 (?) */ +# endif +# ifdef VXWORKS +# include +# else +# include +# endif +# include +# ifdef OS390 +# include +# else +# include /* TCP_NODELAY */ +# endif +# include +# endif +# endif +#endif + +#ifdef WITH_FASTCGI +# include +#endif + +#ifdef WITH_OPENSSL +# define OPENSSL_NO_KRB5 +# include +# include +# include +# ifndef ALLOW_OLD_VERSIONS +# if (OPENSSL_VERSION_NUMBER < 0x00905100L) +# error "Must use OpenSSL 0.9.6 or later" +# endif +# endif +#endif + +#ifdef WITH_GZIP +# ifndef WITH_ZLIB +# define WITH_ZLIB +# endif +#endif + +#ifdef WITH_CASEINSENSITIVETAGS +# define SOAP_STRCMP soap_tag_cmp /* case insensitve XML element/attribute names */ +#else +# define SOAP_STRCMP strcmp /* case sensitive XML element/attribute names */ +#endif + +#ifdef WITH_ZLIB +# include +#endif + +#ifndef PALM +# include /* for isnan() */ +#endif + +/* #define DEBUG */ /* Uncomment to debug sending (in file SENT.log) receiving (in file RECV.log) and messages (in file TEST.log) */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define soap_get0(soap) (((soap)->bufidx>=(soap)->buflen && soap_recv(soap)) ? EOF : (unsigned char)(soap)->buf[(soap)->bufidx]) +#define soap_get1(soap) (((soap)->bufidx>=(soap)->buflen && soap_recv(soap)) ? EOF : (unsigned char)(soap)->buf[(soap)->bufidx++]) +#define soap_revget1(soap) ((soap)->bufidx--) +#define soap_unget(soap, c) ((soap)->ahead = c) +#define soap_register_plugin(soap, plugin) soap_register_plugin_arg(soap, plugin, NULL) +#define soap_imode(soap, n) ((soap)->mode = (soap)->imode = (n)) +#define soap_set_imode(soap, n) ((soap)->mode = (soap)->imode |= (n)) +#define soap_clr_imode(soap, n) ((soap)->mode = (soap)->imode &= ~(n)) +#define soap_omode(soap, n) ((soap)->mode = (soap)->omode = (n)) +#define soap_set_omode(soap, n) ((soap)->mode = (soap)->omode |= (n)) +#define soap_clr_omode(soap, n) ((soap)->mode = (soap)->omode &= ~(n)) +#define soap_destroy(soap) soap_delete((soap), NULL) + +#ifdef WIN32 +# ifndef UNDER_CE +# include +# include +# endif +# include +/* # include */ /* Alternative: use winsock2 (not available with eVC) */ +/* WR[ */ +# ifdef WITH_IPV6 +# include +# include +# endif +#else +# ifdef VXWORKS +# include +# include +# include +# endif +/* ]WR */ +# ifndef MAC_CARBON +# ifndef PALM +# include +# include +# include +# include +# endif +# endif +#endif + +#ifdef WIN32 +# define SOAP_SOCKET SOCKET +#else +# define SOAP_SOCKET int +# define closesocket(n) close(n) +#endif + +#define soap_valid_socket(n) ((n) >= 0) +#define SOAP_INVALID_SOCKET (-1) + +#if defined(SYMBIAN) +# define LONG64 long +# define ULONG64 unsigned LONG64 +#elif !defined(WIN32) +# define LONG64 long long +# define ULONG64 unsigned LONG64 +#elif defined(UNDER_CE) +# define LONG64 __int64 +# define ULONG64 unsigned LONG64 +#elif defined(__BORLANDC__) +# define LONG64 __int64 +# define ULONG64 unsigned LONG64 +#endif + +#if defined(WIN32) +# define soap_int32 __int32 +#elif defined(SYMBIAN) +# define soap_int32 long +#elif defined(PALM) +# define soap_int32 Int32 +#else +# define soap_int32 int32_t +#endif + +/* UCS-4 requires 32 bits (0-7FFFFFFF, the sign bit is used by gSOAP to distinguish XML entities) */ +typedef soap_int32 soap_wchar; + +#ifdef WIN32 +# define SOAP_EINTR WSAEINTR +# define SOAP_EAGAIN WSAEWOULDBLOCK +# define SOAP_EWOULDBLOCK WSAEWOULDBLOCK +# define SOAP_EINPROGRESS WSAEINPROGRESS +#else +# define SOAP_EINTR EINTR +# define SOAP_EAGAIN EAGAIN +# ifdef SYMBIAN +# define SOAP_EWOULDBLOCK 9898 +# define SOAP_EINPROGRESS 9899 +# else +# define SOAP_EWOULDBLOCK EWOULDBLOCK +# define SOAP_EINPROGRESS EINPROGRESS +# endif +#endif + +#ifdef WIN32 +# ifdef UNDER_CE +# define soap_errno GetLastError() +# define soap_socket_errno GetLastError() +# else +# define soap_errno GetLastError() +# define soap_socket_errno WSAGetLastError() +# endif +#else +# define soap_errno errno +# define soap_socket_errno errno +#endif + +#ifndef SOAP_BUFLEN +# ifndef WITH_LEAN +# define SOAP_BUFLEN (32768) /* buffer length for socket packets, also used by gethostbyname_r so don't make this too small */ +# else +# define SOAP_BUFLEN (2048) +# endif +#endif +#ifndef SOAP_LABLEN +# ifndef WITH_LEAN +# define SOAP_LABLEN (256) /* initial look-aside buffer length */ +# else +# define SOAP_LABLEN (64) +# endif +#endif +#ifndef SOAP_PTRHASH +# ifndef WITH_LEAN +# define SOAP_PTRHASH (1024) /* size of pointer analysis hash table (must be power of 2) */ +# else +# define SOAP_PTRHASH (16) +# endif +#endif +#ifndef SOAP_IDHASH +# ifndef WITH_LEAN +# define SOAP_IDHASH (1999) /* prime size of hash table for parsed id/ref */ +# else +# define SOAP_IDHASH (199) +# endif +#endif +#ifndef SOAP_BLKLEN +# define SOAP_BLKLEN (256) /* size of blocks to collect long strings and XML attributes */ +#endif +#ifndef SOAP_TAGLEN +# define SOAP_TAGLEN (256) /* maximum length of XML element tag/attribute name + 1 */ +#endif +#ifndef SOAP_HDRLEN +# ifndef WITH_LEAN +# define SOAP_HDRLEN (8192) /* maximum length of HTTP header line (must be >4096 to read cookies) */ +# else +# define SOAP_HDRLEN (1024) +# endif +#endif +#ifndef SOAP_MAXDIMS +# define SOAP_MAXDIMS (16) /* maximum array dimensions (array nestings) must be less than 64 to protect soap->tmpbuf */ +#endif + +#ifndef SOAP_MAXLOGS +# define SOAP_MAXLOGS (3) /* max number of debug logs per struct soap environment */ +# define SOAP_INDEX_RECV (0) +# define SOAP_INDEX_SENT (1) +# define SOAP_INDEX_TEST (2) +#endif + +#ifndef SOAP_MAXKEEPALIVE +# define SOAP_MAXKEEPALIVE (100) /* max iterations to keep server connection alive */ +#endif + +#ifndef SOAP_MAXARRAYSIZE +# define SOAP_MAXARRAYSIZE (100000) /* "trusted" max size of inbound SOAP array for compound array allocation */ +#endif + +#ifdef VXWORKS +# ifdef __INCmathh +# include +# ifndef HAVE_ISNAN +# define HAVE_ISNAN +# endif +# define soap_isnan(num) isNan(num) +# endif +#endif + +#ifdef WIN32 +# include +# ifndef HAVE_ISNAN +# define HAVE_ISNAN +# endif +# define soap_isnan(num) _isnan(num) +#endif + +#ifdef SUN_OS +# define soap_isnan(n) isnan(n) +#endif + +#if !defined(HAVE_ISNAN) && (defined(_MATH_H) || defined(_MATH_INCLUDED)) +# define HAVE_ISNAN +#endif + +#ifndef soap_isnan +# ifdef HAVE_ISNAN +# define soap_isnan(n) isnan(n) +# else +# define soap_isnan(_) (0) +# endif +#endif + +extern const struct soap_double_nan { unsigned int n1, n2; } soap_double_nan; + +#ifdef VXWORKS +# ifndef FLT_MAX +# define FLT_MAX _ARCH_FLT_MAX +# endif +# ifndef DBL_MAX +# define DBL_MAX _ARCH_DBL_MAX +# endif +#endif + +#ifndef FLT_NAN +# ifdef HAVE_ISNAN +# define FLT_NAN (*(float*)&soap_double_nan) +# else +# define FLT_NAN (0.0) +# endif +#endif + +#ifndef FLT_PINFTY +# ifdef FLT_MAX +# define FLT_PINFTY FLT_MAX +# else +# ifdef HUGE_VAL +# define FLT_PINFTY (float)HUGE_VAL +# else +# ifdef FLOAT_MAX +# define FLT_PINFTY FLOAT_MAX +# else +# define FLT_PINFTY (3.40282347e+38) +# endif +# endif +# endif +#endif + +#ifndef FLT_NINFTY +# define FLT_NINFTY (-FLT_PINFTY) +#endif + +#ifndef DBL_NAN +# ifdef HAVE_ISNAN +# define DBL_NAN (*(double*)&soap_double_nan) +# else +# define DBL_NAN (0.0) +# endif +#endif + +#ifndef DBL_PINFTY +# ifdef DBL_MAX +# define DBL_PINFTY DBL_MAX +# else +# ifdef HUGE_VAL +# define DBL_PINFTY (double)HUGE_VAL +# else +# ifdef DOUBLE_MAX +# define DBL_PINFTY DOUBLE_MAX +# else +# define DBL_PINFTY (1.7976931348623157e+308) +# endif +# endif +# endif +#endif + +#ifndef DBL_NINFTY +# define DBL_NINFTY (-DBL_PINFTY) +#endif + +#define soap_ispinfd(n) ((n) >= DBL_PINFTY) +#define soap_ispinff(n) ((n) >= FLT_PINFTY) +#define soap_isninfd(n) ((n) <= DBL_NINFTY) +#define soap_isninff(n) ((n) <= FLT_NINFTY) + +/* gSOAP error codes */ + +#define SOAP_EOF EOF +#define SOAP_ERR EOF +#define SOAP_OK 0 +#define SOAP_CLI_FAULT 1 +#define SOAP_SVR_FAULT 2 +#define SOAP_TAG_MISMATCH 3 +#define SOAP_TYPE 4 +#define SOAP_SYNTAX_ERROR 5 +#define SOAP_NO_TAG 6 +#define SOAP_IOB 7 +#define SOAP_MUSTUNDERSTAND 8 +#define SOAP_NAMESPACE 9 +/* #define SOAP_OBJ_MISMATCH 10 obsolete */ +#define SOAP_TAG_END 10 +#define SOAP_FATAL_ERROR 11 +#define SOAP_FAULT 12 +#define SOAP_NO_METHOD 13 +#define SOAP_GET_METHOD 14 +#define SOAP_EOM 15 +#define SOAP_NULL 16 +#define SOAP_MULTI_ID 17 +#define SOAP_MISSING_ID 18 +#define SOAP_HREF 19 +#define SOAP_TCP_ERROR 20 +#define SOAP_HTTP_ERROR 21 +#define SOAP_SSL_ERROR 22 +#define SOAP_ZLIB_ERROR 23 +#define SOAP_DIME_ERROR 24 +#define SOAP_DIME_HREF 25 +#define SOAP_DIME_MISMATCH 26 +#define SOAP_DIME_END 27 +#define SOAP_MIME_ERROR 28 +#define SOAP_VERSIONMISMATCH 29 +#define SOAP_PLUGIN_ERROR 30 +#define SOAP_DATAENCODINGUNKNOWN 31 +#define SOAP_REQUIRED 32 +#define SOAP_PROHIBITED 33 +#define SOAP_OCCURS 34 +#define SOAP_LENGTH 35 + +#define soap_xml_error_check(e) ((e) == SOAP_TAG_MISMATCH || (e) == SOAP_TAG_END || (e) == SOAP_SYNTAX_ERROR || (e) == SOAP_NAMESPACE || (e) == SOAP_MULTI_ID || (e) == SOAP_MISSING_ID || (e) == SOAP_REQUIRED || (e) == SOAP_PROHIBITED || (e) == SOAP_OCCURS || (e) == SOAP_LENGTH || (e) == SOAP_NULL || (e) == SOAP_HREF) +#define soap_soap_error_check(e) ((e) == SOAP_CLI_FAULT || (e) == SOAP_SVR_FAULT || (e) == SOAP_VERSIONMISMATCH || (e) == SOAP_MUSTUNDERSTAND || (e) == SOAP_FAULT || (e) == SOAP_NO_METHOD) +#define soap_tcp_error_check(e) ((e) == SOAP_EOF || (e) == SOAP_TCP_ERROR) +#define soap_ssl_error_check(e) ((e) == SOAP_SSL_ERROR) +#define soap_zlib_error_check(e) ((e) == SOAP_ZLIB_ERROR) +#define soap_mime_error_check(e) ((e) == SOAP_MIME_ERROR) +#define soap_dime_error_check(e) ((e) == SOAP_DIME_ERROR || (e) == SOAP_DIME_MISMATCH) +#define soap_http_error_check(e) ((e) == SOAP_HTTP_ERROR || (e) == SOAP_GET_METHOD || ((e) >= 100 && (e) < 600)) + +/* gSOAP HTTP response status codes 100 to 600 are reserved */ + +/* Special gSOAP HTTP response status codes */ + +#define SOAP_STOP 1000 /* No HTTP response */ +#define SOAP_HTML 1001 /* Custom HTML response */ +#define SOAP_FILE 1002 /* Custom file-based response */ + +/* gSOAP HTTP request status codes */ + +#define SOAP_POST 1003 +#define SOAP_GET 1104 + +/* gSOAP DIME */ + +#define SOAP_DIME_CF 0x01 +#define SOAP_DIME_ME 0x02 +#define SOAP_DIME_MB 0x04 +#define SOAP_DIME_VERSION 0x08 /* DIME version 1 */ +#define SOAP_DIME_MEDIA 0x10 +#define SOAP_DIME_ABSURI 0x20 + +/* gSOAP ZLIB */ + +#define SOAP_ZLIB_NONE 0x00 +#define SOAP_ZLIB_DEFLATE 0x01 +#define SOAP_ZLIB_INFLATE 0x02 +#define SOAP_ZLIB_GZIP 0x02 + +/* gSOAP transport, connection, and content encoding modes */ + +typedef soap_int32 soap_mode; + +#define SOAP_IO 0x00000003 /* IO mask */ +#define SOAP_IO_FLUSH 0x00000000 /* flush output immediately, no buffering */ +#define SOAP_IO_BUFFER 0x00000001 /* buffer output in packets of size SOAP_BUFLEN */ +#define SOAP_IO_STORE 0x00000002 /* store entire output to determine length for transport */ +#define SOAP_IO_CHUNK 0x00000003 /* use HTTP chunked transfer AND buffer packets */ + +#define SOAP_IO_LENGTH 0x00000004 +#define SOAP_IO_KEEPALIVE 0x00000008 + +#define SOAP_ENC_LATIN 0x00800010 /* iso-8859-1 encoding */ +#define SOAP_ENC_XML 0x00000020 /* plain XML encoding, no HTTP header */ +#define SOAP_ENC_DIME 0x00000040 +#define SOAP_ENC_MIME 0x00000080 +#define SOAP_ENC_ZLIB 0x00000100 +#define SOAP_ENC_SSL 0x00000200 + +#define SOAP_XML_STRICT 0x00001000 /* strict validation */ +#define SOAP_XML_CANONICAL 0x00002000 /* C14N canonical XML */ +#define SOAP_XML_TREE 0x00004000 +#define SOAP_XML_GRAPH 0x00008000 +#define SOAP_XML_NIL 0x00010000 +#define SOAP_XML_DOM 0x00020000 +#define SOAP_XML_SEC 0x00040000 /* reserved for WS security */ + +#define SOAP_C_NOIOB 0x00100000 +#define SOAP_C_UTFSTRING 0x00200000 +#define SOAP_C_MBSTRING 0x00400000 + +#define SOAP_DOM_TREE 0x01000000 +#define SOAP_DOM_NODE 0x02000000 + +#define SOAP_IO_DEFAULT SOAP_IO_FLUSH + +/* SSL client/server authentication settings */ + +#define SOAP_SSL_NO_AUTHENTICATION 0x00 /* for testing purposes */ +#define SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION 0x01 /* client requires server to authenticate */ +#define SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION 0x02 /* server requires client to authenticate */ + +#define SOAP_SSL_DEFAULT SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION + +/* */ + +#define SOAP_BEGIN 0 +#define SOAP_IN_ENVELOPE 2 +#define SOAP_IN_HEADER 3 +#define SOAP_END_HEADER 4 +#define SOAP_IN_BODY 5 +#define SOAP_END_BODY 6 +#define SOAP_END_ENVELOPE 7 +#define SOAP_END 8 + +/* DEBUG macros */ + +#ifndef WITH_LEAN +# ifdef DEBUG +# ifndef SOAP_DEBUG +# define SOAP_DEBUG +# endif +# endif +#endif + +#ifdef SOAP_DEBUG +# ifndef SOAP_MESSAGE +# define SOAP_MESSAGE fprintf +# endif +# ifndef DBGLOG +# define DBGLOG(DBGFILE, CMD) \ +{ if (soap)\ + { if (!soap->fdebug[SOAP_INDEX_##DBGFILE])\ + soap_open_logfile(soap, SOAP_INDEX_##DBGFILE);\ + if (soap->fdebug[SOAP_INDEX_##DBGFILE])\ + { FILE *fdebug = soap->fdebug[SOAP_INDEX_##DBGFILE];\ + CMD;\ + fflush(fdebug);\ + }\ + }\ +} +# endif +# ifndef DBGMSG +# define DBGMSG(DBGFILE, MSG, LEN) \ +{ if (soap)\ + { if (!soap->fdebug[SOAP_INDEX_##DBGFILE])\ + soap_open_logfile(soap, SOAP_INDEX_##DBGFILE);\ + if (soap->fdebug[SOAP_INDEX_##DBGFILE])\ + { fwrite((MSG), 1, (LEN), soap->fdebug[SOAP_INDEX_##DBGFILE]);\ + fflush(soap->fdebug[SOAP_INDEX_##DBGFILE]);\ + }\ + }\ +} +# endif +#else +# define DBGLOG(DBGFILE, CMD) +# define DBGMSG(DBGFILE, MSG, LEN) +#endif + +struct Namespace +{ const char *id; + const char *ns; + const char *in; + char *out; +}; + +struct soap_nlist +{ struct soap_nlist *next; + unsigned int level; + short index; /* corresponding entry in ns mapping table */ + char *ns; /* only set when parsed ns URI is not in the ns mapping table */ + char id[1]; /* the actual string value flows into the allocated region below this struct */ +}; + +struct soap_blist +{ struct soap_blist *next; + char *ptr; + size_t size; +}; + +struct soap_array +{ void *__ptr; + int __size; +}; + +/* pointer serialization management */ +struct soap_plist +{ struct soap_plist *next; + const void *ptr; + const struct soap_array *array; + int type; + int id; + char mark1; + char mark2; +}; + +/* class allocation list */ +struct soap_clist +{ struct soap_clist *next; + void *ptr; + int type; + int size; + void (*fdelete)(struct soap_clist*); +}; + +struct soap_attribute +{ struct soap_attribute *next; + char *value; + size_t size; + char *ns; + short visible; + char name[1]; /* the actual name string flows into the allocated region below this struct */ +}; + +struct soap_cookie +{ struct soap_cookie *next; + char *name; + char *value; + char *domain; + char *path; + long expire; /* client-side: local time to expire; server-side: seconds to expire */ + unsigned int version; + short secure; + short session; /* server-side */ + short env; /* server-side: got cookie from client */ + short modified; /* server-side: client cookie was modified */ +}; + +#ifdef __cplusplus +SOAP_FMAC1 struct soap_multipart* SOAP_FMAC2 soap_next_multipart(struct soap_multipart*); +class soap_multipart_iterator +{ public: + struct soap_multipart *content; + bool operator==(const soap_multipart_iterator& iter) const + { return content == iter.content; } + bool operator!=(const soap_multipart_iterator& iter) const + { return content != iter.content; } + struct soap_multipart &operator*() const + { return *content; } + soap_multipart_iterator &operator++() + { content = soap_next_multipart(content); return *this; } + soap_multipart_iterator() : content(NULL) + { } + soap_multipart_iterator(struct soap_multipart *p) : content(p) + { } +}; +#endif + +struct soap_dime +{ size_t count; + size_t size; + size_t chunksize; + size_t buflen; + char flags; + char *ptr; + const char *id; + const char *type; + const char *options; + struct soap_multipart *list; /* list of DIME attachments received */ + struct soap_multipart *first, *last; /* temporary in/out queue */ +#ifdef __cplusplus + soap_multipart_iterator begin() + { soap_multipart_iterator iter(list); return iter; }; + soap_multipart_iterator end() + { soap_multipart_iterator iter(NULL); return iter; }; +#endif +}; + +struct soap_mime +{ char *boundary; /* MIME boundary */ + const char *start; /* MIME start ID */ + struct soap_multipart *list; /* list of DIME attachments received */ + struct soap_multipart *first, *last; /* temporary in/out queue */ +#ifdef __cplusplus + soap_multipart_iterator begin() + { soap_multipart_iterator iter(list); return iter; }; + soap_multipart_iterator end() + { soap_multipart_iterator iter(NULL); return iter; }; +#endif +}; + +/* RFC2045 MIME content transfer encodings */ +enum soap_mime_encoding +{ SOAP_MIME_NONE, + SOAP_MIME_7BIT, + SOAP_MIME_8BIT, + SOAP_MIME_BINARY, + SOAP_MIME_QUOTED_PRINTABLE, + SOAP_MIME_BASE64, + SOAP_MIME_IETF_TOKEN, + SOAP_MIME_X_TOKEN +}; + +/* DIME/MIME multipart list */ +struct soap_multipart +{ struct soap_multipart *next; + char *ptr; /* points to raw data content */ + size_t size; /* size of data content */ + const char *id; /* DIME/MIME content ID */ + const char *type; /* DIME/MIME type (MIME type format) */ + const char *options; /* DIME options */ + enum soap_mime_encoding encoding; /* MIME Content-Transfer-Encoding */ + const char *location; /* MIME Content-Location (optional) */ + const char *description; /* MIME Content-Description (optional) */ +#ifdef __cplusplus + typedef soap_multipart_iterator iterator; +#endif +}; + +struct soap_dom_attribute +{ struct soap_dom_attribute *next; + const char *nstr; + char *name; + char *data; + wchar_t *wide; + struct soap *soap; +#ifdef __cplusplus + struct soap_dom_attribute &set(const char *nstr, const char *name); // set namespace and name + struct soap_dom_attribute &set(const char *data); // set data + void unlink(); + soap_dom_attribute(); + soap_dom_attribute(struct soap *soap); + soap_dom_attribute(struct soap *soap, const char *nstr, const char *name, const char *data); + ~soap_dom_attribute(); +#endif +}; + +#ifdef __cplusplus +class soap_dom_iterator +{ public: + struct soap_dom_element *elt; + const char *nstr; + const char *name; + int type; + bool operator==(const soap_dom_iterator&) const; + bool operator!=(const soap_dom_iterator&) const; + struct soap_dom_element &operator*() const; + soap_dom_iterator &operator++(); + soap_dom_iterator(); + soap_dom_iterator(struct soap_dom_element*); + ~soap_dom_iterator(); +}; +#endif + +struct soap_dom_element +{ struct soap_dom_element *next; /* next sibling */ + struct soap_dom_element *prnt; /* parent */ + struct soap_dom_element *elts; /* first child element */ + struct soap_dom_attribute *atts; /* first child attribute */ + const char *nstr; /* namespace string */ + char *name; /* element tag name */ + char *data; /* element content data (with SOAP_C_UTFSTRING flag set) */ + wchar_t *wide; /* element content data */ + int type; /* optional: serialized C/C++ data type */ + void *node; /* optional: pointer to serialized C/C++ data */ + struct soap *soap; +#ifdef __cplusplus + typedef soap_dom_iterator iterator; + struct soap_dom_element &set(const char *nstr, const char *name); + struct soap_dom_element &set(const char *data); + struct soap_dom_element &set(void *node, int type); + struct soap_dom_element &add(struct soap_dom_element*); + struct soap_dom_element &add(struct soap_dom_element&); + struct soap_dom_element &add(struct soap_dom_attribute*); + struct soap_dom_element &add(struct soap_dom_attribute&); + soap_dom_iterator begin(); + soap_dom_iterator end(); + soap_dom_iterator find(const char *nstr, const char *name); + soap_dom_iterator find(int type); + void unlink(); + soap_dom_element(); + soap_dom_element(struct soap *soap); + soap_dom_element(struct soap *soap, const char *nstr, const char *name); + soap_dom_element(struct soap *soap, const char *nstr, const char *name, const char *data); + soap_dom_element(struct soap *soap, const char *nstr, const char *name, void *node, int type); + ~soap_dom_element(); +#endif +}; + +#if defined(__cplusplus) && !defined(WITH_LEAN) +} +extern ostream &operator<<(ostream&, const struct soap_dom_element&); +extern istream &operator>>(istream&, struct soap_dom_element&); +extern "C" { +#endif + +struct soap +{ short version; /* 1 = SOAP1.1 and 2 = SOAP1.2 (set automatically from namespace URI in nsmap table) */ + short copy; /* 1 = copy of another soap struct */ + soap_mode mode; + soap_mode imode; + soap_mode omode; + const char *float_format; /* points to user-definable format string for floats (<1024 chars) */ + const char *double_format; /* points to user-definable format string for doubles (<1024 chars) */ + const char *dime_id_format; /* points to user-definable format string for integer DIME id ( 0, gives socket recv timeout in seconds, < 0 in usec */ + int send_timeout; /* when > 0, gives socket send timeout in seconds, < 0 in usec */ + int connect_timeout; /* when > 0, gives socket connect() timeout in seconds, < 0 in usec */ + int accept_timeout; /* when > 0, gives socket accept() timeout in seconds, < 0 in usec */ + int socket_flags; /* socket recv() and send() flags, e.g. set to MSG_NOSIGNAL to disable sigpipe */ + int connect_flags; /* connect() SOL_SOCKET sockopt flags, e.g. set to SO_DEBUG to debug socket */ + int bind_flags; /* bind() SOL_SOCKET sockopt flags, e.g. set to SO_REUSEADDR to enable reuse */ + int accept_flags; /* accept() SOL_SOCKET sockopt flags */ + const struct Namespace *namespaces; /* Pointer to global namespace mapping table */ + struct Namespace *local_namespaces; /* Local namespace mapping table */ + struct soap_nlist *nlist; /* namespace stack */ + struct soap_blist *blist; /* block allocation stack */ + struct soap_clist *clist; /* class instance allocation list */ + void *alist; /* memory allocation list */ + struct soap_ilist *iht[SOAP_IDHASH]; + struct soap_plist *pht[SOAP_PTRHASH]; + struct SOAP_ENV__Header *header; + struct SOAP_ENV__Fault *fault; + void *user; /* to pass user-defined data */ + struct soap_plugin *plugins; /* linked list of plug-in data */ + char *userid; /* HTTP Basic authorization userid */ + char *passwd; /* HTTP Basic authorization passwd */ + int (*fpost)(struct soap*, const char*, const char*, int, const char*, const char*, size_t); + int (*fget)(struct soap*); + int (*fposthdr)(struct soap*, const char*, const char*); + int (*fresponse)(struct soap*, int, size_t); + int (*fparse)(struct soap*); + int (*fparsehdr)(struct soap*, const char*, const char*); + int (*fresolve)(struct soap*, const char*, struct in_addr* inaddr); + int (*fconnect)(struct soap*, const char*, const char*, int); + int (*fdisconnect)(struct soap*); + int (*fclosesocket)(struct soap*, SOAP_SOCKET); + int (*fshutdownsocket)(struct soap*, SOAP_SOCKET, int); + int (*fopen)(struct soap*, const char*, const char*, int); + int (*faccept)(struct soap*, int, struct sockaddr*, int *n); + int (*fclose)(struct soap*); + int (*fsend)(struct soap*, const char*, size_t); + size_t (*frecv)(struct soap*, char*, size_t); + int (*fpoll)(struct soap*); + int (*fprepareinit)(struct soap*); + int (*fpreparesend)(struct soap*, const char*, size_t); + int (*fpreparerecv)(struct soap*, const char*, size_t); + int (*fignore)(struct soap*, const char*); + int (*fserveloop)(struct soap*); + void *(*fplugin)(struct soap*, const char*); + void *(*fdimereadopen)(struct soap*, void*, const char*, const char*, const char*); + void *(*fdimewriteopen)(struct soap*, const char*, const char*, const char*); + void (*fdimereadclose)(struct soap*, void*); + void (*fdimewriteclose)(struct soap*, void*); + size_t (*fdimeread)(struct soap*, void*, char*, size_t); + int (*fdimewrite)(struct soap*, void*, const char*, size_t); + int master; + int socket; +#if defined(__cplusplus) && !defined(WITH_LEAN) + ostream *os; + istream *is; +#else + void *os; /* preserve alignment */ + void *is; /* preserve alignment */ +#endif +#ifndef UNDER_CE + int sendfd; + int recvfd; +#else + FILE *sendfd; + FILE *recvfd; + char errorstr[256]; + wchar_t werrorstr[256]; +#endif + size_t bufidx; + size_t buflen; + soap_wchar ahead; + short cdata; + short body; + unsigned int level; + size_t count; /* message length counter */ + size_t length; /* message length as set by HTTP header */ + char *labbuf; /* look-aside buffer */ + size_t lablen; /* look-aside buffer allocated length */ + size_t labidx; /* look-aside buffer index to available part */ + char buf[SOAP_BUFLEN];/* send and receive buffer */ + char tmpbuf[1024]; /* output buffer for HTTP headers, simpleType values, attribute names, and DIME >=1024 bytes */ + char msgbuf[1024]; /* output buffer for (error) messages <=1024 bytes */ + char tag[SOAP_TAGLEN]; + char id[SOAP_TAGLEN]; + char href[SOAP_TAGLEN]; + char type[SOAP_TAGLEN]; + char arrayType[SOAP_TAGLEN]; + char arraySize[SOAP_TAGLEN]; + char arrayOffset[SOAP_TAGLEN]; + short other; + short root; + short position; + int positions[SOAP_MAXDIMS]; + struct soap_attribute *attributes; /* attribute list */ + short encoding; + short mustUnderstand; + short null; + short ns; + short part; + short alloced; + short peeked; + short keep_alive; + size_t chunksize; + size_t chunkbuflen; + char endpoint[SOAP_TAGLEN]; + char path[SOAP_TAGLEN]; + char host[SOAP_TAGLEN]; + char *action; + char *authrealm; /* HTTP authentication realm */ + char *prolog; /* XML declaration prolog */ + int port; + unsigned int max_keep_alive; + const char *proxy_host; /* Proxy Server host name */ + int proxy_port; /* Proxy Server port (default = 8080) */ + const char *proxy_userid; /* Proxy Authorization user name */ + const char *proxy_passwd; /* Proxy Authorization password */ + int status; /* -1 when request, else error code to be returned by server */ + int error; + int errmode; + int errnum; + unsigned long idnum; + unsigned long ip; + struct soap_dime dime; + struct soap_mime mime; + struct soap_dom_element *dom; +#if !defined(WITH_LEAN) || defined(SOAP_DEBUG) + const char *logfile[SOAP_MAXLOGS]; + FILE *fdebug[SOAP_MAXLOGS]; +#endif +#ifndef WITH_LEAN + struct soap_cookie *cookies; + const char *cookie_domain; + const char *cookie_path; + int cookie_max; +#endif +#ifdef WITH_OPENSSL + int (*fsslauth)(struct soap*); + int (*fsslverify)(int, X509_STORE_CTX*); + BIO *bio; + SSL *ssl; + SSL_CTX *ctx; + short require_server_auth; + short require_client_auth; + short rsa; /* when set, use RSA instead of DH */ + const char *keyfile; + const char *password; + const char *dhfile; + const char *cafile; + const char *capath; + const char *randfile; + SSL_SESSION *session; + char session_host[SOAP_TAGLEN]; + int session_port; +#endif +#ifdef WITH_ZLIB + short zlib_state; /* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_INFLATE */ + short zlib_in; /* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_GZIP */ + short zlib_out; /* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_GZIP */ + z_stream d_stream; /* decompression stream */ + char z_buf[SOAP_BUFLEN]; /* buffer */ + size_t z_buflen; + unsigned short z_level; /* compression level to be used (0=none, 1=fast to 9=best) */ + uLong z_crc; /* internal gzip crc */ + float z_ratio_in; /* detected compression ratio compressed_length/length of inbound message */ + float z_ratio_out; /* detected compression ratio compressed_length/length of outbound message */ +#endif +/* WR[ */ +#ifdef WMW_RPM_IO + void *rpmreqid; +#endif /* WMW_RPM_IO */ +/* ]WR */ +}; + +struct soap_code_map +{ long code; + const char *string; +}; + +/* forwarding list */ +struct soap_flist +{ struct soap_flist *next; + int type; + void *ptr; + unsigned int level; + void (*fcopy)(struct soap*, int, int, void*, const void*, size_t); +}; + +/* id-ref forwarding list */ +struct soap_ilist +{ struct soap_ilist *next; + int type; + size_t size; + void *link; + void *copy; + struct soap_flist *flist; + void *ptr; + unsigned int level; + char id[1]; /* the actual id string value flows into the allocated region below this struct */ +}; + +struct soap_plugin +{ struct soap_plugin *next; + const char *id; + void *data; + int (*fcopy)(struct soap *soap, struct soap_plugin *dst, struct soap_plugin *src); + void (*fdelete)(struct soap *soap, struct soap_plugin *p); /* should delete fields of plugin only and not free(p) */ +}; + +#ifndef WITH_NONAMESPACES +extern SOAP_NMAC struct Namespace namespaces[]; +#endif + +#ifdef HAVE_STRRCHR +# define soap_strrchr(s, t) strrchr(s, t) +#else + SOAP_FMAC1 char* SOAP_FMAC2 soap_strrchr(const char *s, int t); +#endif + +#ifdef HAVE_STRTOL +# define soap_strtol(s, t, b) strtol(s, t, b) +#else + SOAP_FMAC1 long SOAP_FMAC2 soap_strtol(const char *s, char **t, int b); +#endif + +#ifdef HAVE_STRTOUL +# define soap_strtoul(s, t, b) strtoul(s, t, b) +#else + SOAP_FMAC1 unsigned long SOAP_FMAC2 soap_strtoul(const char *s, char **t, int b); +#endif + +SOAP_FMAC1 void SOAP_FMAC2 soap_fault(struct soap*); +SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultcode(struct soap*); +SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultstring(struct soap*); +SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultdetail(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_serializeheader(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putheader(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getheader(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_serializefault(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putfault(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getfault(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_poll(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_connect_command(struct soap*, int, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_connect(struct soap*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_bind(struct soap*, const char*, int, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_accept(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_accept(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_server_context(struct soap*, unsigned short, const char*, const char*, const char*, const char*, const char*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_client_context(struct soap*, unsigned short, const char*, const char*, const char*, const char*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_puthttphdr(struct soap*, int status, size_t count); + +SOAP_FMAC1 const char* SOAP_FMAC2 soap_get_header_attribute(struct soap*, const char*, const char*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_decode_key(char*, size_t, const char*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_decode_val(char*, size_t, const char*); + +SOAP_FMAC1 size_t SOAP_FMAC2 soap_hash(const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_endpoint(struct soap*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_flush_raw(struct soap*, const char*, size_t); +SOAP_FMAC1 int SOAP_FMAC2 soap_flush(struct soap*); +SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_get(struct soap*); +SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_getchar(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_tag_cmp(const char*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_fault(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_sender_fault(struct soap*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_receiver_fault(struct soap*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_sender_error(struct soap*, const char*, const char*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_receiver_error(struct soap*, const char*, const char*, int); + +SOAP_FMAC1 int SOAP_FMAC2 soap_send_raw(struct soap*, const char*, size_t); +SOAP_FMAC1 int SOAP_FMAC2 soap_recv_raw(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_recv(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_send(struct soap*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_send2(struct soap*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_send3(struct soap*, const char*, const char*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_pututf8(struct soap*, unsigned long); +SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_getutf8(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_putbase64(struct soap*, const unsigned char*, int); +SOAP_FMAC1 unsigned char* SOAP_FMAC2 soap_getbase64(struct soap*, int*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_puthex(struct soap*, const unsigned char*, int); +SOAP_FMAC1 unsigned char* SOAP_FMAC2 soap_gethex(struct soap*, int*); + + +SOAP_FMAC1 struct soap_ilist* SOAP_FMAC2 soap_lookup(struct soap*, const char*); +SOAP_FMAC1 struct soap_ilist* SOAP_FMAC2 soap_enter(struct soap*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_resolve(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_lookup_id(struct soap*, void *p, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_lookup(struct soap*, const void *p, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_enter(struct soap*, const void *p, const struct soap_array *a, int n, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_array_pointer_lookup(struct soap*, const void *p, const struct soap_array *a, int n, int t, struct soap_plist**); + +SOAP_FMAC1 int SOAP_FMAC2 soap_embed(struct soap *soap, const void *p, const struct soap_array *a, int n, const char *tag, int type); + +SOAP_FMAC1 void SOAP_FMAC2 soap_begin_count(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_begin_send(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_end_send(struct soap*); + +SOAP_FMAC1 void SOAP_FMAC2 soap_embedded(struct soap*, const void *p, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_reference(struct soap*, const void *p, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_array_reference(struct soap*, const void *p, const struct soap_array *a, int n, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_embedded_id(struct soap*, int id, const void *p, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_is_embedded(struct soap*, struct soap_plist*); +SOAP_FMAC1 int SOAP_FMAC2 soap_is_single(struct soap*, struct soap_plist*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_embedded(struct soap*, struct soap_plist*); + +SOAP_FMAC1 const struct soap_code_map* SOAP_FMAC2 soap_code(const struct soap_code_map*, const char *str); +SOAP_FMAC1 long SOAP_FMAC2 soap_int_code(const struct soap_code_map*, const char *str, long other); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_str_code(const struct soap_code_map*, long code); + +SOAP_FMAC1 int SOAP_FMAC2 soap_getline(struct soap*, char*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_begin_recv(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_end_recv(struct soap*); + +SOAP_FMAC1 void* SOAP_FMAC2 soap_malloc(struct soap*, size_t); +SOAP_FMAC1 void SOAP_FMAC2 soap_dealloc(struct soap*, void*); +SOAP_FMAC1 struct soap_clist * SOAP_FMAC2 soap_link(struct soap*, void*, int, int, void (*fdelete)(struct soap_clist*)); +SOAP_FMAC1 void SOAP_FMAC2 soap_unlink(struct soap*, const void*); +SOAP_FMAC1 void SOAP_FMAC2 soap_free(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_lookup_type(struct soap*, const char *id); + +SOAP_FMAC1 void* SOAP_FMAC2 soap_id_lookup(struct soap*, const char *id, void **p, int t, size_t n, unsigned int k); +SOAP_FMAC1 void* SOAP_FMAC2 soap_id_forward(struct soap*, const char *id, void *p, int st, int tt, size_t n, unsigned int k, void(*fcopy)(struct soap*, int, int, void*, const void*, size_t)); +SOAP_FMAC1 void* SOAP_FMAC2 soap_id_enter(struct soap*, const char *id, void *p, int t, size_t n, unsigned int k, const char *type, const char *arrayType, void *(*finstantiate)(struct soap*, int, const char*, const char*, size_t*)); +SOAP_FMAC1 void SOAP_FMAC2 soap_fcopy(struct soap *soap, int st, int tt, void *p, const void *q, size_t n); + +SOAP_FMAC1 int SOAP_FMAC2 soap_size(const int *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_getoffsets(const char *, const int *, int *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_getsize(const char *, const char *, int *); +SOAP_FMAC1 int SOAP_FMAC2 soap_getsizes(const char *, int *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_getposition(const char *, int *); + +SOAP_FMAC1 char* SOAP_FMAC2 soap_putsize(struct soap*, const char *, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_putsizesoffsets(struct soap*, const char *, const int *, const int *, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_putsizes(struct soap*, const char *, const int *, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_putoffset(struct soap*, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_putoffsets(struct soap*, const int *, int); + +SOAP_FMAC1 int SOAP_FMAC2 soap_closesock(struct soap*); + +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_new(void); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_new1(int); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_new2(int, int); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_copy(struct soap*); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_copy_context(struct soap*,struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_init(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_init1(struct soap*, int); +SOAP_FMAC1 void SOAP_FMAC2 soap_init2(struct soap*, int, int); +SOAP_FMAC1 void SOAP_FMAC2 soap_done(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_cleanup(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_begin(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_end(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_delete(struct soap*, void*); + +#ifdef SOAP_DEBUG +SOAP_FMAC1 void SOAP_FMAC2 soap_set_recv_logfile(struct soap*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_sent_logfile(struct soap*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_test_logfile(struct soap*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_close_logfiles(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_open_logfile(struct soap*, int); +#endif + +SOAP_FMAC1 const char* SOAP_FMAC2 soap_value(struct soap*); + +SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_advance(struct soap*); +SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_skip(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_match_tag(struct soap*, const char*, const char *); +SOAP_FMAC1 int SOAP_FMAC2 soap_match_array(struct soap*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_element(struct soap*, const char*, int, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_begin_out(struct soap*, const char *tag, int id, const char *type); +SOAP_FMAC1 int SOAP_FMAC2 soap_array_begin_out(struct soap*, const char *tag, int id, const char *type, const char *offset); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_ref(struct soap*, const char *tag, int id, int href); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_href(struct soap*, const char *tag, int id, const char *ref, const char *val); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_null(struct soap*, const char *tag, int id, const char *type); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_id(struct soap*, const char *tag, int id, const void *p, const struct soap_array *a, int d, const char *type, int n); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_result(struct soap*, const char *tag); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_end_out(struct soap*, const char *tag); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_start_end_out(struct soap*, const char *tag); + +SOAP_FMAC1 int SOAP_FMAC2 soap_attribute(struct soap*, const char*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_element_begin_in(struct soap*, const char *tag, int nillable); + +SOAP_FMAC1 int SOAP_FMAC2 soap_element_end_in(struct soap*, const char *tag); + +SOAP_FMAC1 int SOAP_FMAC2 soap_peek_element(struct soap*); + +SOAP_FMAC1 void SOAP_FMAC2 soap_retry(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_revert(struct soap*); + +SOAP_FMAC1 char* SOAP_FMAC2 soap_strdup(struct soap*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_string_out(struct soap*, const char *s, int flag); +SOAP_FMAC1 char* SOAP_FMAC2 soap_string_in(struct soap*, int, long, long); +SOAP_FMAC1 int SOAP_FMAC2 soap_wstring_out(struct soap*, const wchar_t *s, int flag); +SOAP_FMAC1 wchar_t* SOAP_FMAC2 soap_wstring_in(struct soap*, int, long, long); + +SOAP_FMAC1 int SOAP_FMAC2 soap_match_namespace(struct soap*, const char *, const char*, int n1, int n2); + +SOAP_FMAC1 int SOAP_FMAC2 soap_set_namespaces(struct soap*, struct Namespace*); + +SOAP_FMAC1 void SOAP_FMAC2 soap_pop_namespace(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_push_namespace(struct soap*, const char *,const char *); + +SOAP_FMAC1 int SOAP_FMAC2 soap_new_block(struct soap*); +SOAP_FMAC1 void* SOAP_FMAC2 soap_push_block(struct soap*, size_t); +SOAP_FMAC1 void SOAP_FMAC2 soap_pop_block(struct soap*); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_size_block(struct soap*, size_t); +SOAP_FMAC1 char* SOAP_FMAC2 soap_first_block(struct soap*); +SOAP_FMAC1 char* SOAP_FMAC2 soap_next_block(struct soap*); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_block_size(struct soap*); +SOAP_FMAC1 char* SOAP_FMAC2 soap_save_block(struct soap*, char*, int); +SOAP_FMAC1 void SOAP_FMAC2 soap_end_block(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_begin_out(struct soap*); +SOAP_FMAC1 int soap_envelope_end_out(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_begin_in(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_end_in(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_body_begin_out(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_body_end_out(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_body_begin_in(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_body_end_in(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_recv_header(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_response(struct soap*, int); + +SOAP_FMAC1 int SOAP_FMAC2 soap_send_fault(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_recv_fault(struct soap*); + +SOAP_FMAC1 void SOAP_FMAC2 soap_print_fault(struct soap*, FILE*); +SOAP_FMAC1 void SOAP_FMAC2 soap_print_fault_location(struct soap*, FILE*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_s2byte(struct soap*, const char*, char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2short(struct soap*, const char*, short*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2int(struct soap*, const char*, int*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2long(struct soap*, const char*, long*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2LONG64(struct soap*, const char*, LONG64*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2float(struct soap*, const char*, float*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2double(struct soap*, const char*, double*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedByte(struct soap*, const char*, unsigned char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedShort(struct soap*, const char*, unsigned short*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedInt(struct soap*, const char*, unsigned int*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedLong(struct soap*, const char*, unsigned long*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2ULONG64(struct soap*, const char*, ULONG64*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2dateTime(struct soap*, const char*, time_t*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2string(struct soap*, const char*, char**); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2QName(struct soap*, const char*, char**); + +SOAP_FMAC1 char* SOAP_FMAC2 soap_s2base64(struct soap*, const unsigned char*, char*, size_t); + +SOAP_FMAC1 const char* SOAP_FMAC2 soap_byte2s(struct soap*, char); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_short2s(struct soap*, short); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_int2s(struct soap*, int); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_long2s(struct soap*, long); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_LONG642s(struct soap*, LONG64); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_float2s(struct soap*, float); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_double2s(struct soap*, double); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedByte2s(struct soap*, unsigned char); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedShort2s(struct soap*, unsigned short); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedInt2s(struct soap*, unsigned int); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedLong2s(struct soap*, unsigned long); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_ULONG642s(struct soap*, ULONG64); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_dateTime2s(struct soap*, time_t); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_QName2s(struct soap*, const char*); + +SOAP_FMAC1 const char* SOAP_FMAC2 soap_base642s(struct soap*, const char*, char*, size_t, size_t*); + +SOAP_FMAC1 int* SOAP_FMAC2 soap_inint(struct soap*, const char *tag, int *p, const char *, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_inbyte(struct soap*, const char *tag, char *p, const char *, int); +SOAP_FMAC1 long* SOAP_FMAC2 soap_inlong(struct soap*, const char *tag, long *p, const char *, int); +SOAP_FMAC1 LONG64* SOAP_FMAC2 soap_inLONG64(struct soap*, const char *tag, LONG64 *p, const char *, int); +SOAP_FMAC1 short* SOAP_FMAC2 soap_inshort(struct soap*, const char *tag, short *p, const char *, int); +SOAP_FMAC1 float* SOAP_FMAC2 soap_infloat(struct soap*, const char *tag, float *p, const char *, int); +SOAP_FMAC1 double* SOAP_FMAC2 soap_indouble(struct soap*, const char *tag, double *p, const char *, int); +SOAP_FMAC1 unsigned char* SOAP_FMAC2 soap_inunsignedByte(struct soap*, const char *tag, unsigned char *p, const char *, int); +SOAP_FMAC1 unsigned short* SOAP_FMAC2 soap_inunsignedShort(struct soap*, const char *tag, unsigned short *p, const char *, int); +SOAP_FMAC1 unsigned int* SOAP_FMAC2 soap_inunsignedInt(struct soap*, const char *tag, unsigned int *p, const char *, int); +SOAP_FMAC1 unsigned long* SOAP_FMAC2 soap_inunsignedLong(struct soap*, const char *tag, unsigned long *p, const char *, int); +SOAP_FMAC1 ULONG64* SOAP_FMAC2 soap_inULONG64(struct soap*, const char *tag, ULONG64 *p, const char *, int); +SOAP_FMAC1 time_t* SOAP_FMAC2 soap_indateTime(struct soap*, const char *tag, time_t *p, const char *, int); +SOAP_FMAC1 char** SOAP_FMAC2 soap_instring(struct soap*, const char *tag, char **p, const char *, int, int, long, long); +SOAP_FMAC1 wchar_t** SOAP_FMAC2 soap_inwstring(struct soap*, const char *tag, wchar_t **p, const char *, int, long, long); +SOAP_FMAC1 char** SOAP_FMAC2 soap_inliteral(struct soap*, const char *tag, char **p); +SOAP_FMAC1 wchar_t** SOAP_FMAC2 soap_inwliteral(struct soap*, const char *tag, wchar_t **p); + +SOAP_FMAC1 int SOAP_FMAC2 soap_outbyte(struct soap*, const char *tag, int id, const char *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outshort(struct soap*, const char *tag, int id, const short *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outint(struct soap*, const char *tag, int id, const int *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outlong(struct soap*, const char *tag, int id, const long *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outLONG64(struct soap*, const char *tag, int id, const LONG64 *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outfloat(struct soap*, const char *tag, int id, const float *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outdouble(struct soap*, const char *tag, int id, const double *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedByte(struct soap*, const char *tag, int id, const unsigned char *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedShort(struct soap*, const char *tag, int id, const unsigned short *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedInt(struct soap*, const char *tag, int id, const unsigned int *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedLong(struct soap*, const char *tag, int id, const unsigned long *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outULONG64(struct soap*, const char *tag, int id, const ULONG64 *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outdateTime(struct soap*, const char *tag, int id, const time_t *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outstring(struct soap*, const char *tag, int id, char *const*p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outwstring(struct soap*, const char *tag, int id, wchar_t *const*p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outliteral(struct soap*, const char *tag, char *const*p); +SOAP_FMAC1 int SOAP_FMAC2 soap_outwliteral(struct soap*, const char *tag, wchar_t *const*p); + +#ifndef WITH_LEANER +SOAP_FMAC1 int SOAP_FMAC2 soap_element_dime(struct soap *, const char*, int, const void*, const struct soap_array*, const char*, const char*, const char*, int, const char*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_move(struct soap*, long); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_tell(struct soap*); +SOAP_FMAC1 char* SOAP_FMAC2 soap_dime_option(struct soap*, unsigned short, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getdimehdr(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getdime(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putdimehdr(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putdime(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getmimehdr(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getmime(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putmimehdr(struct soap*, struct soap_multipart*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putmime(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_dime(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_mime(struct soap*, const char *boundary, const char *start); +SOAP_FMAC1 void SOAP_FMAC2 soap_clr_dime(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_clr_mime(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_dime_attachment(struct soap*, char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_mime_attachment(struct soap*, char *ptr, size_t size, enum soap_mime_encoding encoding, const char *type, const char *id, const char *location, const char *description); +SOAP_FMAC1 struct soap_multipart* SOAP_FMAC2 soap_next_multipart(struct soap_multipart*); +#endif + +SOAP_FMAC1 int SOAP_FMAC2 soap_register_plugin_arg(struct soap*, int (*fcreate)(struct soap*, struct soap_plugin*, void*), void*); +SOAP_FMAC1 void* SOAP_FMAC2 soap_lookup_plugin(struct soap*, const char*); + +SOAP_FMAC1 const char* SOAP_FMAC2 soap_attr_value(struct soap *soap, const char *name, int flag); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_attr(struct soap *soap, const char *name, const char *value); +SOAP_FMAC1 void SOAP_FMAC2 soap_clr_attr(struct soap *soap); + +#ifdef WITH_COOKIES +SOAP_FMAC1 size_t SOAP_FMAC2 soap_encode_cookie(const char*, char*, size_t); +SOAP_FMAC1 extern struct soap_cookie* SOAP_FMAC2 soap_set_cookie(struct soap*, const char*, const char*, const char*, const char*); +SOAP_FMAC1 extern struct soap_cookie* SOAP_FMAC2 soap_cookie(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern char* SOAP_FMAC2 soap_cookie_value(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern long SOAP_FMAC2 soap_cookie_expire(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern int SOAP_FMAC2 soap_set_cookie_expire(struct soap*, const char*, long, const char*, const char*); +SOAP_FMAC1 extern int SOAP_FMAC2 soap_set_cookie_session(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern int SOAP_FMAC2 soap_clr_cookie_session(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern void SOAP_FMAC2 soap_clr_cookie(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern int SOAP_FMAC2 soap_getenv_cookies(struct soap*); +SOAP_FMAC1 extern struct soap_cookie* SOAP_FMAC2 soap_copy_cookies(struct soap*); +SOAP_FMAC1 extern void SOAP_FMAC2 soap_free_cookies(struct soap*); +#endif + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.0f.c b/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.0f.c new file mode 100644 index 0000000..b4750a4 --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.0f.c @@ -0,0 +1,12026 @@ +/* + +stdsoap2.c[pp] 2.7.0f + +Runtime environment. + +gSOAP XML Web services tools +Copyright (C) 2000-2004, Robert van Engelen, Genivia, Inc., All Rights Reserved. + +Contributors: + +Wind River Systems, Inc., for the following additions (marked WR[...]): + - vxWorks compatible + - Support for IPv6. + +-------------------------------------------------------------------------------- + + This software is released under one of the following three licenses: + GPL, the gSOAP public license, or Genivia's license for commercial use. + +-------------------------------------------------------------------------------- +gSOAP public license. + +The contents of this file are subject to the gSOAP Public License Version 1.3 +(the "License"); you may not use this file except in compliance with the +License. You may obtain a copy of the License at +http://www.cs.fsu.edu/~engelen/soaplicense.html +Software distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +for the specific language governing rights and limitations under the License. + +The Initial Developer of the Original Code is Robert A. van Engelen. +Copyright (C) 2000-2004, Robert van Engelen, Genivia, Inc., All Rights Reserved. +-------------------------------------------------------------------------------- +GPL license. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA + +Author contact information: +engelen@genivia.com / engelen@acm.org +-------------------------------------------------------------------------------- +A commercial use license is available from Genivia, Inc., contact@genivia.com +-------------------------------------------------------------------------------- + +Installation note: + +Win32 build needs winsock.dll (Visual C++ "wsock32.lib") +To do this in Visual C++ 6.0, go to "Project", "settings", select the "Link" +tab (the project file needs to be selected in the file view) and add +"wsock32.lib" to the "Object/library modules" entry + +On Mac OS X with gcc (GCC) 3.1 20020420 (prerelease) you MUST compile with +-fstack_check when using -O2 because gcc 3.1 has a bug that smashes the stack +when locally allocated data exceeds 64K. + +*/ + +#include "stdsoap2.h" + +#ifdef __cplusplus +SOAP_SOURCE_STAMP("@(#) stdsoap2.cpp ver 2.7.0f 2005-02-28 12:00:00 GMT") +extern "C" { +#else +SOAP_SOURCE_STAMP("@(#) stdsoap2.c ver 2.7.0f 2005-02-28 12:00:00 GMT") +#endif + +/* 8bit character representing unknown/nonrepresentable character data (e.g. not supported by current locale) */ +#ifndef SOAP_UNKNOWN_CHAR +#define SOAP_UNKNOWN_CHAR (127) +#endif + +/* EOF=-1 */ +#define SOAP_LT (soap_wchar)(-2) /* XML character '<' */ +#define SOAP_TT (soap_wchar)(-3) /* XML character '' */ +#define SOAP_QT (soap_wchar)(-5) /* XML character '"' */ +#define SOAP_AP (soap_wchar)(-6) /* XML character ''' */ + +#define SOAP_BOM (soap_wchar)(0xFEFF) /* UTF BOM is Unicode FEFF */ + +#define soap_blank(c) ((c) >= 0 && (c) <= 32) +#define soap_notblank(c) ((c) > 32) +#define soap_hash_ptr(p) (((unsigned long)(p) >> 3) & (SOAP_PTRHASH - 1)) + +static int soap_isxdigit(int); +static soap_wchar soap_char(struct soap*); + +#ifndef WITH_NOIDREF +static void soap_update_ptrs(struct soap*, char*, char*, long); +static int soap_has_copies(struct soap*, const char*, const char*); +static struct soap_ilist *soap_hlookup(struct soap*, const char*); +static void soap_init_iht(struct soap*); +static void soap_free_iht(struct soap*); +static void soap_init_pht(struct soap*); +static void soap_free_pht(struct soap*); +#endif + +static int soap_set_error(struct soap*, const char*, const char*, const char*, int); +static int soap_copy_fault(struct soap*, const char*, const char*, const char*); +static int soap_getattrval(struct soap*, char*, size_t, soap_wchar); +static void soap_set_local_namespaces(struct soap*); +static void *fplugin(struct soap*, const char*); + +#ifndef WITH_LEAN +static const char *soap_set_validation_fault(struct soap*, const char*, const char*); +static int soap_isnumeric(struct soap*, const char*); +static time_t soap_timegm(struct tm*); +#endif + +#ifdef SOAP_DEBUG +static void soap_init_logs(struct soap*); +static void soap_close_logfile(struct soap*, int); +static void soap_set_logfile(struct soap*, int, const char*); +#endif + +#ifdef WITH_FAST +static int soap_append_lab(struct soap*, const char*, size_t); +#endif + +#ifndef WITH_LEANER +static struct soap_multipart *soap_new_multipart(struct soap*, struct soap_multipart**, struct soap_multipart**, char*, size_t); +static int soap_putdimefield(struct soap*, const char*, size_t); +static char *soap_getdimefield(struct soap*, size_t); +static void soap_select_mime_boundary(struct soap*); +static int soap_valid_mime_boundary(struct soap*); +#endif + +#ifdef WITH_GZIP +static int soap_getgziphdr(struct soap*); +#endif + +#ifdef WITH_OPENSSL +static int ssl_auth_init(struct soap*); +static int ssl_verify_callback(int, X509_STORE_CTX*); +static int ssl_password(char*, int, int, void *); +static const char *ssl_error(struct soap*, int); +/* This callback is included for future references. It should not be deleted +static DH *ssl_tmp_dh(SSL*, int, int); +*/ +#endif + +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +static const char *soap_decode(char*, size_t, const char*, const char*); +#endif + +#ifndef WITH_NOHTTP +static soap_wchar soap_getchunkchar(struct soap*); +static const char *http_error(struct soap*, int); +static int http_post(struct soap*, const char*, const char*, int, const char*, const char*, size_t); +static int http_get(struct soap*); +static int http_send_header(struct soap*, const char*); +static int http_post_header(struct soap*, const char*, const char*); +static int http_response(struct soap*, int, size_t); +static int http_parse(struct soap*); +static int http_parse_header(struct soap*, const char*, const char*); +#endif + +#ifndef WITH_NOIO +static int fsend(struct soap*, const char*, size_t); +static size_t frecv(struct soap*, char*, size_t); +static int tcp_init(struct soap*); +static const char *tcp_error(struct soap*); +static int tcp_gethost(struct soap*, const char *addr, struct in_addr *inaddr); +static int tcp_connect(struct soap*, const char *endpoint, const char *host, int port); +static int tcp_accept(struct soap*, int, struct sockaddr*, int*); +static int tcp_disconnect(struct soap*); +static int tcp_closesocket(struct soap*, SOAP_SOCKET); +static int tcp_shutdownsocket(struct soap*, SOAP_SOCKET, int); +static const char *soap_strerror(struct soap*); +#endif + +/* WR[ */ +#ifdef VXWORKS +static int vx_nonblocking = TRUE; /* ioctl argument */ +#endif +/* ]WR */ + +#if defined(PALM) && !defined(PALM_2) +unsigned short errno; +#endif + +#ifndef PALM_1 +static const char soap_env1[42] = "http://schemas.xmlsoap.org/soap/envelope/"; +static const char soap_enc1[42] = "http://schemas.xmlsoap.org/soap/encoding/"; +static const char soap_env2[40] = "http://www.w3.org/2003/05/soap-envelope"; +static const char soap_enc2[40] = "http://www.w3.org/2003/05/soap-encoding"; +static const char soap_rpc[35] = "http://www.w3.org/2003/05/soap-rpc"; +#endif + +#ifndef PALM_1 +const struct soap_double_nan soap_double_nan = {0xFFFFFFFF, 0xFFFFFFFF}; +static const char soap_base64o[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char soap_base64i[81] = "\76XXX\77\64\65\66\67\70\71\72\73\74\75XXXXXXX\00\01\02\03\04\05\06\07\10\11\12\13\14\15\16\17\20\21\22\23\24\25\26\27\30\31XXXXXX\32\33\34\35\36\37\40\41\42\43\44\45\46\47\50\51\52\53\54\55\56\57\60\61\62\63"; +#endif + +static const char soap_padding[3] = "\0\0"; +#define SOAP_STR_PADDING (soap_padding) +#define SOAP_STR_EOS (soap_padding) + +#ifndef WITH_LEAN +static const struct soap_code_map html_entity_codes[] = /* entities for XHTML parsing */ +{ { 160, "nbsp" }, + { 161, "iexcl" }, + { 162, "cent" }, + { 163, "pound" }, + { 164, "curren" }, + { 165, "yen" }, + { 166, "brvbar" }, + { 167, "sect" }, + { 168, "uml" }, + { 169, "copy" }, + { 170, "ordf" }, + { 171, "laquo" }, + { 172, "not" }, + { 173, "shy" }, + { 174, "reg" }, + { 175, "macr" }, + { 176, "deg" }, + { 177, "plusmn" }, + { 178, "sup2" }, + { 179, "sup3" }, + { 180, "acute" }, + { 181, "micro" }, + { 182, "para" }, + { 183, "middot" }, + { 184, "cedil" }, + { 185, "sup1" }, + { 186, "ordm" }, + { 187, "raquo" }, + { 188, "frac14" }, + { 189, "frac12" }, + { 190, "frac34" }, + { 191, "iquest" }, + { 192, "Agrave" }, + { 193, "Aacute" }, + { 194, "Acirc" }, + { 195, "Atilde" }, + { 196, "Auml" }, + { 197, "Aring" }, + { 198, "AElig" }, + { 199, "Ccedil" }, + { 200, "Egrave" }, + { 201, "Eacute" }, + { 202, "Ecirc" }, + { 203, "Euml" }, + { 204, "Igrave" }, + { 205, "Iacute" }, + { 206, "Icirc" }, + { 207, "Iuml" }, + { 208, "ETH" }, + { 209, "Ntilde" }, + { 210, "Ograve" }, + { 211, "Oacute" }, + { 212, "Ocirc" }, + { 213, "Otilde" }, + { 214, "Ouml" }, + { 215, "times" }, + { 216, "Oslash" }, + { 217, "Ugrave" }, + { 218, "Uacute" }, + { 219, "Ucirc" }, + { 220, "Uuml" }, + { 221, "Yacute" }, + { 222, "THORN" }, + { 223, "szlig" }, + { 224, "agrave" }, + { 225, "aacute" }, + { 226, "acirc" }, + { 227, "atilde" }, + { 228, "auml" }, + { 229, "aring" }, + { 230, "aelig" }, + { 231, "ccedil" }, + { 232, "egrave" }, + { 233, "eacute" }, + { 234, "ecirc" }, + { 235, "euml" }, + { 236, "igrave" }, + { 237, "iacute" }, + { 238, "icirc" }, + { 239, "iuml" }, + { 240, "eth" }, + { 241, "ntilde" }, + { 242, "ograve" }, + { 243, "oacute" }, + { 244, "ocirc" }, + { 245, "otilde" }, + { 246, "ouml" }, + { 247, "divide" }, + { 248, "oslash" }, + { 249, "ugrave" }, + { 250, "uacute" }, + { 251, "ucirc" }, + { 252, "uuml" }, + { 253, "yacute" }, + { 254, "thorn" }, + { 255, "yuml" }, + { 0, NULL } +}; +#endif + +#ifndef WITH_NOIO +#ifndef WITH_LEAN +static const struct soap_code_map h_error_codes[] = +{ +#ifdef HOST_NOT_FOUND + { HOST_NOT_FOUND, "Host not found" }, +#endif +#ifdef TRY_AGAIN + { TRY_AGAIN, "Try Again" }, +#endif +#ifdef NO_RECOVERY + { NO_RECOVERY, "No Recovery" }, +#endif +#ifdef NO_DATA + { NO_DATA, "No Data" }, +#endif +#ifdef NO_ADDRESS + { NO_ADDRESS, "No Address" }, +#endif + { 0, NULL } +}; +#endif +#endif + +#ifndef WITH_NOHTTP +#ifndef WITH_LEAN +static const struct soap_code_map h_http_error_codes[] = +{ { 201, "Created" }, + { 202, "Accepted" }, + { 203, "Non-Authoritative Information" }, + { 204, "No Content" }, + { 205, "Reset Content" }, + { 206, "Partial Content" }, + { 300, "Multiple Choices" }, + { 301, "Moved Permanently" }, + { 302, "Found" }, + { 303, "See Other" }, + { 304, "Not Modified" }, + { 305, "Use Proxy" }, + { 307, "Temporary Redirect" }, + { 400, "Bad Request" }, + { 401, "Unauthorized" }, + { 402, "Payment Required" }, + { 403, "Forbidden" }, + { 404, "Not Found" }, + { 405, "Method Not Allowed" }, + { 406, "Not Acceptable" }, + { 407, "Proxy Authentication Required" }, + { 408, "Request Time-out" }, + { 409, "Conflict" }, + { 410, "Gone" }, + { 411, "Length Required" }, + { 412, "Precondition Failed" }, + { 413, "Request Entity Too Large" }, + { 414, "Request-URI Too Large" }, + { 415, "Unsupported Media Type" }, + { 416, "Requested range not satisfiable" }, + { 417, "Expectation Failed" }, + { 500, "Internal Server Error" }, + { 501, "Not Implemented" }, + { 502, "Bad Gateway" }, + { 503, "Service Unavailable" }, + { 504, "Gateway Time-out" }, + { 505, "HTTP Version not supported" }, + { 0, NULL } +}; +#endif +#endif + +#ifdef WITH_OPENSSL +static const struct soap_code_map h_ssl_error_codes[] = +{ +#define _SSL_ERROR(e) { e, #e } + _SSL_ERROR(SSL_ERROR_SSL), + _SSL_ERROR(SSL_ERROR_ZERO_RETURN), + _SSL_ERROR(SSL_ERROR_WANT_READ), + _SSL_ERROR(SSL_ERROR_WANT_WRITE), + _SSL_ERROR(SSL_ERROR_WANT_CONNECT), + _SSL_ERROR(SSL_ERROR_WANT_X509_LOOKUP), + _SSL_ERROR(SSL_ERROR_SYSCALL), + { 0, NULL } +}; +#endif + +#ifndef WITH_LEANER +static const struct soap_code_map mime_codes[] = +{ { SOAP_MIME_7BIT, "7bit" }, + { SOAP_MIME_8BIT, "8bit" }, + { SOAP_MIME_BINARY, "binary" }, + { SOAP_MIME_QUOTED_PRINTABLE, "quoted-printable" }, + { SOAP_MIME_BASE64, "base64" }, + { SOAP_MIME_IETF_TOKEN, "ietf-token" }, + { SOAP_MIME_X_TOKEN, "x-token" }, + { 0, NULL } +}; +#endif + +#ifdef WIN32 +static int tcp_done = 0; +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +fsend(struct soap *soap, const char *s, size_t n) +{ register int nwritten; +#if defined(__cplusplus) && !defined(WITH_LEAN) + if (soap->os) + { soap->os->write(s, n); + if (soap->os->good()) + return SOAP_OK; + return SOAP_EOF; + } +#endif + while (n) + { if (soap_valid_socket(soap->socket)) + { +#ifndef WITH_LEAN + if (soap->send_timeout) + { struct timeval timeout; + fd_set fd; + if (soap->send_timeout > 0) + { timeout.tv_sec = soap->send_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->send_timeout/1000000; + timeout.tv_usec = -soap->send_timeout%1000000; + } + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->socket, &fd); + for (;;) + { register int r = select((SOAP_SOCKET)(soap->socket + 1), NULL, &fd, &fd, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + return SOAP_EOF; + } + if (soap_socket_errno != SOAP_EINTR) + { soap->errnum = soap_socket_errno; + return SOAP_EOF; + } + } + } +#endif +#ifdef WITH_OPENSSL + if (soap->ssl) + nwritten = SSL_write(soap->ssl, s, n); + else +#endif +#ifndef PALM + nwritten = send((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags); +#else + nwritten = send((SOAP_SOCKET)soap->socket, (void*)s, n, soap->socket_flags); +#endif + if (nwritten <= 0) + { +#ifdef WITH_OPENSSL + int err; + if (soap->ssl && (err = SSL_get_error(soap->ssl, nwritten)) != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) + return SOAP_EOF; +#endif + if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EWOULDBLOCK && soap_socket_errno != SOAP_EAGAIN) + { soap->errnum = soap_socket_errno; + return SOAP_EOF; + } + nwritten = 0; /* and call write() again */ + } + } + else + { +#ifdef WITH_FASTCGI + nwritten = fwrite((void*)s, 1, n, stdout); + fflush(stdout); +#else +#ifdef UNDER_CE + nwritten = fwrite(s, 1, n, soap->sendfd); +#else +/* WR[ */ +#ifdef VXWORKS +#ifdef WMW_RPM_IO + if (soap->rpmreqid) + { httpBlockPut(soap->rpmreqid, s, n); + nwritten = n; + } + else + nwritten = fwrite(s, sizeof(char), n, fdopen(soap->sendfd, "w")); +#else + nwritten = fwrite(s, sizeof(char), n, fdopen(soap->sendfd, "w")); +#endif /* WMW_RPM_IO */ +#else +/* ]WR */ + nwritten = write((SOAP_SOCKET)soap->sendfd, s, n); +/* WR[ */ +#endif +/* ]WR */ +#endif +#endif + if (nwritten <= 0) + { if (soap_errno != SOAP_EINTR && soap_errno != SOAP_EWOULDBLOCK && soap_errno != SOAP_EAGAIN) + { soap->errnum = soap_errno; + return SOAP_EOF; + } + nwritten = 0; /* and call write() again */ + } + } + n -= nwritten; + s += nwritten; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_flush_raw(struct soap *soap, const char *s, size_t n) +{ if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) + { register char *t; + if (!(t = (char*)soap_push_block(soap, n))) + return soap->error = SOAP_EOM; + memcpy(t, s, n); +#ifndef WITH_LEANER + if (soap->fpreparesend) + return soap->fpreparesend(soap, s, n); +#endif + return SOAP_OK; + } +#ifndef WITH_LEANER + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) + { char t[16]; + sprintf(t, "\r\n%lX\r\n" + (soap->chunksize ? 0 : 2), (unsigned long)n); + DBGMSG(SENT, t, strlen(t)); + if ((soap->error = soap->fsend(soap, t, strlen(t)))) + return soap->error; + soap->chunksize += n; + } + DBGMSG(SENT, s, n); +#endif + return soap->error = soap->fsend(soap, s, n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_flush(struct soap *soap) +{ if (soap->bufidx) + { +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { soap->d_stream.next_in = (Byte*)soap->buf; + soap->d_stream.avail_in = (unsigned int)soap->bufidx; +#ifdef WITH_GZIP + soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->bufidx); +#endif + do + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating %u bytes\n", soap->d_stream.avail_in)); + if (deflate(&soap->d_stream, Z_NO_FLUSH) != Z_OK) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to deflate: %s\n", soap->d_stream.msg?soap->d_stream.msg:"")); + return soap->error = SOAP_ZLIB_ERROR; + } + if (!soap->d_stream.avail_out) + { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN)) + return soap->error; + soap->d_stream.next_out = (Byte*)soap->z_buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + } + } while (soap->d_stream.avail_in); + } + else +#endif + if (soap_flush_raw(soap, soap->buf, soap->bufidx)) + return soap->error; + soap->bufidx = 0; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send_raw(struct soap *soap, const char *s, size_t n) +{ if (!n) + return SOAP_OK; + if (soap->mode & SOAP_IO_LENGTH) + { soap->count += n; +#ifndef WITH_LEANER + if (soap->fpreparesend && (soap->mode & SOAP_IO) != SOAP_IO_STORE) + return soap->fpreparesend(soap, s, n); +#endif + return SOAP_OK; + } + if (soap->mode & SOAP_IO) + { register size_t i = SOAP_BUFLEN - soap->bufidx; + while (n >= i) + { memcpy(soap->buf + soap->bufidx, s, i); + soap->bufidx = SOAP_BUFLEN; + if (soap_flush(soap)) + return soap->error; + s += i; + n -= i; + i = SOAP_BUFLEN; + } + memcpy(soap->buf + soap->bufidx, s, n); + soap->bufidx += n; + return SOAP_OK; + } + return soap_flush_raw(soap, s, n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send(struct soap *soap, const char *s) +{ if (s) + return soap_send_raw(soap, s, strlen(s)); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send2(struct soap *soap, const char *s1, const char *s2) +{ if (soap_send(soap, s1)) + return soap->error; + return soap_send(soap, s2); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send3(struct soap *soap, const char *s1, const char *s2, const char *s3) +{ if (soap_send(soap, s1) + || soap_send(soap, s2)) + return soap->error; + return soap_send(soap, s3); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static size_t +frecv(struct soap *soap, char *s, size_t n) +{ register int r; + soap->errnum = 0; +#if defined(__cplusplus) && !defined(WITH_LEAN) + if (soap->is) + { if (soap->is->good()) + return soap->is->read(s, n).gcount(); + return 0; + } +#endif + if (soap_valid_socket(soap->socket)) + { for (;;) + { +#ifndef WITH_LEAN + if (soap->recv_timeout) + { struct timeval timeout; + fd_set fd; + if (soap->recv_timeout > 0) + { timeout.tv_sec = soap->recv_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->recv_timeout/1000000; + timeout.tv_usec = -soap->recv_timeout%1000000; + } + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->socket, &fd); + for (;;) + { r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout); + if (r > 0) + break; + if (r == 0 || soap_socket_errno != SOAP_EINTR) + { soap->errnum = soap_socket_errno; + return 0; + } + } + } +#endif +#ifdef WITH_OPENSSL + if (soap->ssl) + { int err; + r = SSL_read(soap->ssl, s, n); + if ((err = SSL_get_error(soap->ssl, r)) == SSL_ERROR_NONE) + return (size_t)r; + if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) + return 0; + } + else +#endif + { r = recv((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags); + if (r >= 0) + return (size_t)r; + if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EAGAIN && soap_socket_errno != SOAP_EWOULDBLOCK) + { soap->errnum = soap_socket_errno; + return 0; + } + } +#ifndef WITH_LEAN + { struct timeval timeout; + fd_set fd; + timeout.tv_sec = 0; + timeout.tv_usec = 10000; + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->socket, &fd); +#ifdef WITH_OPENSSL + if (soap->ssl && SSL_get_error(soap->ssl, r) == SSL_ERROR_WANT_WRITE) + r = select((SOAP_SOCKET)(soap->socket + 1), NULL, &fd, &fd, &timeout); + else + r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout); +#else + r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout); +#endif + if (r < 0 && soap_socket_errno != SOAP_EINTR) + { soap->errnum = soap_socket_errno; + return 0; + } + } +#endif + } + } +#ifdef WITH_FASTCGI + return fread(s, 1, n, stdin); +#else +#ifdef UNDER_CE + return fread(s, 1, n, soap->recvfd); +#else +/* WR[ */ +#ifdef WMW_RPM_IO + if (soap->rpmreqid) + r = httpBlockRead(soap->rpmreqid, s, n); + else + r = read(soap->recvfd, s, n); + if (r >= 0) + return r; + return 0; +#else +/* ]WR */ + r = read((SOAP_SOCKET)soap->recvfd, s, n); + if (r >= 0) + return (size_t)r; + soap->errnum = soap_errno; + return 0; +/* WR[ */ +#endif +/* ]WR */ +#endif +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static soap_wchar +soap_getchunkchar(struct soap *soap) +{ if (soap->bufidx < soap->buflen) + return soap->buf[soap->bufidx++]; + soap->bufidx = 0; + soap->buflen = soap->chunkbuflen = soap->frecv(soap, soap->buf, SOAP_BUFLEN); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket %d\n", (unsigned int)soap->buflen, soap->socket)); + DBGMSG(RECV, soap->buf, soap->buflen); + if (soap->buflen) + return soap->buf[soap->bufidx++]; + return EOF; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +soap_isxdigit(int c) +{ return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv_raw(struct soap *soap) +{ register size_t ret; +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { if (soap->d_stream.next_out == Z_NULL) + return EOF; + if (soap->d_stream.avail_in || !soap->d_stream.avail_out) + { register int r; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflating\n")); + soap->d_stream.next_out = (Byte*)soap->buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + r = inflate(&soap->d_stream, Z_NO_FLUSH); + if (r == Z_OK || r == Z_STREAM_END) + { soap->bufidx = 0; + soap->buflen = SOAP_BUFLEN - soap->d_stream.avail_out; + if (soap->zlib_in == SOAP_ZLIB_GZIP) + soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen); + if (r == Z_STREAM_END) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out)); + soap->z_ratio_in = (float)soap->d_stream.total_in / (float)soap->d_stream.total_out; + soap->d_stream.next_out = Z_NULL; + } + if (soap->buflen) + { soap->count += soap->buflen; + return SOAP_OK; + } + } + else if (r != Z_BUF_ERROR) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate error: %s\n", soap->d_stream.msg?soap->d_stream.msg:"")); + soap->d_stream.next_out = Z_NULL; + return EOF; + } + } +zlib_again: + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK && !soap->chunksize) + { memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN); + soap->buflen = soap->z_buflen; + } + } +#endif +#ifndef WITH_NOHTTP + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) /* read HTTP chunked transfer */ + { +chunk_again: + if (soap->chunksize) + { soap->buflen = ret = soap->frecv(soap, soap->buf, soap->chunksize > SOAP_BUFLEN ? SOAP_BUFLEN : soap->chunksize); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk: read %u bytes\n", (unsigned int)ret)); + DBGMSG(RECV, soap->buf, ret); + soap->bufidx = 0; + soap->chunksize -= ret; + } + else + { register soap_wchar c; + char *t, tmp[8]; + t = tmp; + if (!soap->chunkbuflen) + { soap->chunkbuflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket %d\n", (unsigned int)ret, soap->socket)); + DBGMSG(RECV, soap->buf, ret); + soap->bufidx = 0; + if (!ret) + return EOF; + } + else + soap->bufidx = soap->buflen; + soap->buflen = soap->chunkbuflen; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk size (%u %u)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen)); + while (!soap_isxdigit((int)(c = soap_getchunkchar(soap)))) + if ((int)c == EOF) + return EOF; + do + *t++ = (char)c; + while (soap_isxdigit((int)(c = soap_getchunkchar(soap))) && t - tmp < 7); + while ((int)c != EOF && c != '\n') + c = soap_getchunkchar(soap); + if ((int)c == EOF) + return EOF; + *t = '\0'; + soap->chunksize = soap_strtoul(tmp, &t, 16); + if (!soap->chunksize) + { soap->chunkbuflen = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of chunked message\n")); + while ((int)c != EOF && c != '\n') + c = soap_getchunkchar(soap); + return EOF; + } + soap->buflen = soap->bufidx + soap->chunksize; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving buf len to %u (%u %s)\n", (unsigned int)soap->buflen, (unsigned int)soap->bufidx, tmp)); + if (soap->buflen > soap->chunkbuflen) + { soap->buflen = soap->chunkbuflen; + soap->chunksize -= soap->buflen - soap->bufidx; + soap->chunkbuflen = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Passed end of buffer for chunked HTTP (%lu bytes left)\n", (unsigned long)(soap->buflen - soap->bufidx))); + } + else if (soap->chunkbuflen) + soap->chunksize = 0; + ret = soap->buflen - soap->bufidx; + if (!ret) + goto chunk_again; + } + } + else +#endif + { soap->bufidx = 0; + soap->buflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket %d\n", (unsigned int)ret, soap->socket)); + DBGMSG(RECV, soap->buf, ret); + } +#ifndef WITH_LEANER + if (soap->fpreparerecv && (soap->error = soap->fpreparerecv(soap, soap->buf, ret))) + return soap->error; +#endif +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { register int r; + memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); + soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx); + soap->d_stream.avail_in = (unsigned int)ret; + soap->d_stream.next_out = (Byte*)soap->buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + r = inflate(&soap->d_stream, Z_NO_FLUSH); + if (r == Z_OK || r == Z_STREAM_END) + { soap->bufidx = 0; + soap->z_buflen = soap->buflen; + soap->buflen = ret = SOAP_BUFLEN - soap->d_stream.avail_out; + if (soap->zlib_in == SOAP_ZLIB_GZIP) + soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %u bytes\n", (unsigned int)ret)); + if (!ret) + goto zlib_again; + if (r == Z_STREAM_END) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out)); + soap->z_ratio_in = (float)soap->d_stream.total_in / (float)soap->d_stream.total_out; + soap->d_stream.next_out = Z_NULL; + } + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to inflate: (%d) %s\n", r, soap->d_stream.msg?soap->d_stream.msg:"")); + soap->d_stream.next_out = Z_NULL; + return EOF; + } + } +#endif + soap->count += ret; + return !ret; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv(struct soap *soap) +{ +#ifndef WITH_LEANER + if (soap->mode & SOAP_ENC_DIME) + { if (soap->dime.buflen) + { char *s; + int i; + unsigned char tmp[12]; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME hdr for chunked DIME is in buffer\n")); + soap->count += soap->dime.buflen - soap->buflen; + soap->buflen = soap->dime.buflen; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Skip padding (%ld bytes)\n", -(long)soap->dime.size&3)); + for (i = -(long)soap->dime.size&3; i > 0; i--) + { soap->bufidx++; + if (soap->bufidx >= soap->buflen) + if (soap_recv_raw(soap)) + return EOF; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME hdr for next chunk\n")); + s = (char*)tmp; + for (i = 12; i > 0; i--) + { *s++ = soap->buf[soap->bufidx++]; + if (soap->bufidx >= soap->buflen) + if (soap_recv_raw(soap)) + return EOF; + } + soap->dime.flags = tmp[0] & 0x7; + soap->dime.size = ((size_t)tmp[8] << 24) | ((size_t)tmp[9] << 16) | ((size_t)tmp[10] << 8) | ((size_t)tmp[11]); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME chunk (%u bytes)\n", (unsigned int)soap->dime.size)); + if (soap->dime.flags & SOAP_DIME_CF) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "More chunking\n")); + soap->dime.chunksize = soap->dime.size; + if (soap->buflen - soap->bufidx >= soap->dime.size) + { soap->dime.buflen = soap->buflen; + soap->buflen = soap->bufidx + soap->dime.chunksize; + } + else + soap->dime.chunksize -= soap->buflen - soap->bufidx; + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Last chunk\n")); + soap->dime.buflen = 0; + soap->dime.chunksize = 0; + } + soap->count = soap->buflen - soap->bufidx; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%u bytes remaining\n", (unsigned int)soap->count)); + return SOAP_OK; + } + if (soap->dime.chunksize) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get next DIME hdr for chunked DIME (%u bytes chunk)\n", (unsigned int)soap->dime.chunksize)); + if (soap_recv_raw(soap)) + return EOF; + if (soap->buflen - soap->bufidx >= soap->dime.chunksize) + { soap->dime.buflen = soap->buflen; + soap->count -= soap->buflen - soap->bufidx - soap->dime.chunksize; + soap->buflen = soap->bufidx + soap->dime.chunksize; + } + else + soap->dime.chunksize -= soap->buflen - soap->bufidx; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%lu bytes remaining, count=%u\n", (unsigned long)(soap->buflen-soap->bufidx), (unsigned int)soap->count)); + return SOAP_OK; + } + } +#endif + return soap_recv_raw(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +soap_wchar +SOAP_FMAC2 +soap_getchar(struct soap *soap) +{ register soap_wchar c; + if (soap->ahead) + { c = soap->ahead; + soap->ahead = 0; + return c; + } + return soap_get1(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +const struct soap_code_map* +SOAP_FMAC2 +soap_code(const struct soap_code_map *map, const char *str) +{ while (map->string) + { if (!strcmp(str, map->string)) /* case sensitive */ + return map; + map++; + } + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +long +SOAP_FMAC2 +soap_int_code(const struct soap_code_map *map, const char *str, long other) +{ while (map->string) + { if (!soap_tag_cmp(str, map->string)) /* case insensitive */ + return map->code; + map++; + } + return other; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_str_code(const struct soap_code_map *map, long code) +{ while (map->code != code && map->string) + map++; + return map->string; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static soap_wchar +soap_char(struct soap *soap) +{ char tmp[8]; + register int i; + register soap_wchar c; + register char *s = tmp; + for (i = 0; i < 7; i++) + { c = soap_get1(soap); + if (c == ';' || (int)c == EOF) + break; + *s++ = (char)c; + } + *s = '\0'; + if (*tmp == '#') + { if (tmp[1] == 'x' || tmp[1] == 'X') + return soap_strtol(tmp + 2, NULL, 16); + return atol(tmp + 1); + } + if (!strcmp(tmp, "lt")) + return '<'; + if (!strcmp(tmp, "gt")) + return '>'; + if (!strcmp(tmp, "amp")) + return '&'; + if (!strcmp(tmp, "quot")) + return '"'; + if (!strcmp(tmp, "apos")) + return '\''; +#ifndef WITH_LEAN + return (soap_wchar)soap_int_code(html_entity_codes, tmp, SOAP_UNKNOWN_CHAR); +#else + return SOAP_UNKNOWN_CHAR; /* use this to represent unknown code */ +#endif +} +#endif + +/******************************************************************************/ +#ifdef WITH_LEAN +soap_wchar +soap_get0(struct soap *soap) +{ if (soap->bufidx >= soap->buflen && soap_recv(soap)) + return EOF; + return (unsigned char)soap->buf[soap->bufidx]; +} +#endif + +/******************************************************************************/ +#ifdef WITH_LEAN +soap_wchar +soap_get1(struct soap *soap) +{ if (soap->bufidx >= soap->buflen && soap_recv(soap)) + return EOF; + return (unsigned char)soap->buf[soap->bufidx++]; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +soap_wchar +SOAP_FMAC2 +soap_get(struct soap *soap) +{ register soap_wchar c; + c = soap->ahead; + if (c) + soap->ahead = 0; + else + c = soap_get1(soap); + for (;;) + { if (soap->cdata) + { if (c == ']') + { c = soap_get1(soap); + if (c == ']') + { soap->cdata = 0; + soap_get1(soap); /* skip > */ + c = soap_get1(soap); + } + else + { soap_revget1(soap); + return ']'; + } + } + else + return c; + } + switch (c) + { case '<': + do c = soap_get1(soap); + while (soap_blank(c)); + if (c == '!' || c == '?' || c == '%') + { if (c == '!') + { c = soap_get1(soap); + if (c == '[') + { do c = soap_get1(soap); + while ((int)c != EOF && c != '['); + if ((int)c == EOF) + break; + soap->cdata = 1; + c = soap_get1(soap); + continue; + } + if (c == '-' && (c = soap_get1(soap)) == '-') + { do + { c = soap_get1(soap); + if (c == '-' && (c = soap_get1(soap)) == '-') + break; + } while ((int)c != EOF); + } + } + while ((int)c != EOF && c != '>') + c = soap_get1(soap); + if ((int)c == EOF) + break; + c = soap_get1(soap); + continue; + } + if (c == '/') + return SOAP_TT; + soap_revget1(soap); + return SOAP_LT; + case '>': + return SOAP_GT; + case '"': + return SOAP_QT; + case '\'': + return SOAP_AP; + case '&': + return soap_char(soap) | 0x80000000; + } + break; + } + return c; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +soap_wchar +SOAP_FMAC2 +soap_advance(struct soap *soap) +{ register soap_wchar c; + while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT) + ; + return c; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +soap_wchar +SOAP_FMAC2 +soap_skip(struct soap *soap) +{ register soap_wchar c; + do c = soap_get(soap); + while (soap_blank(c)); + return c; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_move(struct soap *soap, long n) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving %ld bytes forward\n", (long)n)); + for (; n > 0; n--) + if ((int)soap_getchar(soap) == EOF) + return SOAP_EOF; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_tell(struct soap *soap) +{ return soap->count - soap->buflen + soap->bufidx - (soap->ahead != 0); +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_pututf8(struct soap *soap, register unsigned long c) +{ char tmp[16]; + if (c > 0 && c < 0x80) + { *tmp = (char)c; + return soap_send_raw(soap, tmp, 1); + } +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { register char *t = tmp; + if (c < 0x0800) + *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); + else + { if (c < 0x010000) + *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + else + { if (c < 0x200000) + *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + else + { if (c < 0x04000000) + *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + else + { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + } + *t++ = (char)(0x80 | (c & 0x3F)); + *t = '\0'; + } + else +#endif + sprintf(tmp, "&#%lu;", c); + return soap_send(soap, tmp); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +soap_wchar +SOAP_FMAC2 +soap_getutf8(struct soap *soap) +{ register soap_wchar c, c1, c2, c3, c4; + c = soap_get(soap); + if (c < 0x80 || (soap->mode & SOAP_ENC_LATIN)) + return c; + c1 = soap_get(soap); + if (c1 < 0x80) + { soap_unget(soap, c1); + return c; + } + c1 &= 0x3F; + if (c < 0xE0) + return ((soap_wchar)(c & 0x1F) << 6) | c1; + c2 = (soap_wchar)soap_get1(soap) & 0x3F; + if (c < 0xF0) + return ((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2; + c3 = (soap_wchar)soap_get1(soap) & 0x3F; + if (c < 0xF8) + return ((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3; + c4 = (soap_wchar)soap_get1(soap) & 0x3F; + if (c < 0xFC) + return ((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4; + return ((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(soap_get1(soap) & 0x3F); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_puthex(struct soap *soap, const unsigned char *s, int n) +{ /* TODO: serialize to DOM (as an option) using new soap_s2hex() */ + char d[2]; + register int i; + for (i = 0; i < n; i++) + { register int m = *s++; + d[0] = (char)((m >> 4) + (m > 159 ? '7' : '0')); + m &= 0x0F; + d[1] = (char)(m + (m > 9 ? '7' : '0')); + if (soap_send_raw(soap, d, 2)) + return soap->error; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +unsigned char* +SOAP_FMAC2 +soap_gethex(struct soap *soap, int *n) +{ +#ifdef WITH_FAST + soap->labidx = 0; + for (;;) + { register char *s; + register int i, k; + if (soap_append_lab(soap, NULL, 0)) + return NULL; + s = soap->labbuf + soap->labidx; + k = soap->lablen - soap->labidx; + soap->labidx = soap->lablen; + for (i = 0; i < k; i++) + { register char d1, d2; + register soap_wchar c; + c = soap_get(soap); + if (soap_isxdigit(c)) + { d1 = (char)c; + c = soap_get(soap); + if (soap_isxdigit(c)) + d2 = (char)c; + else + { soap->error = SOAP_TYPE; + return NULL; + } + } + else + { unsigned char *p; + soap_unget(soap, c); + if (n) + *n = (int)(soap->lablen - k + i); + p = (unsigned char*)soap_malloc(soap, soap->lablen - k + i); + if (p) + memcpy(p, soap->labbuf, soap->lablen - k + i); + return p; + } + *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'); + } + } +#else + if (soap_new_block(soap)) + return NULL; + for (;;) + { register int i; + register char *s = (char*)soap_push_block(soap, SOAP_BLKLEN); + if (!s) + { soap_end_block(soap); + return NULL; + } + for (i = 0; i < SOAP_BLKLEN; i++) + { register char d1, d2; + register soap_wchar c = soap_get(soap); + if (soap_isxdigit(c)) + { d1 = (char)c; + c = soap_get(soap); + if (soap_isxdigit(c)) + d2 = (char)c; + else + { soap_end_block(soap); + soap->error = SOAP_TYPE; + return NULL; + } + } + else + { unsigned char *p; + soap_unget(soap, c); + if (n) + *n = soap_size_block(soap, i); + p = (unsigned char*)soap_save_block(soap, NULL, 0); + return p; + } + *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'); + } + } +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putbase64(struct soap *soap, const unsigned char *s, int n) +{ register int i; + register unsigned long m; + char d[4]; + if (!s) + return SOAP_OK; +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { if (!(soap->dom->data = soap_s2base64(soap, s, soap->dom->data, n))) + return soap->error; + return SOAP_OK; + } +#endif + for (; n > 2; n -= 3, s += 3) + { m = s[0]; + m = (m << 8) | s[1]; + m = (m << 8) | s[2]; + for (i = 4; i > 0; m >>= 6) + d[--i] = soap_base64o[m & 0x3F]; + if (soap_send_raw(soap, d, 4)) + return soap->error; + } + if (n > 0) + { m = 0; + for (i = 0; i < n; i++) + m = (m << 8) | *s++; + for (; i < 3; i++) + m <<= 8; + for (i++; i > 0; m >>= 6) + d[--i] = soap_base64o[m & 0x3F]; + for (i = 3; i > n; i--) + d[i] = '='; + if (soap_send_raw(soap, d, 4)) + return soap->error; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +unsigned char* +SOAP_FMAC2 +soap_getbase64(struct soap *soap, int *n, int malloc_flag) +{ +#ifdef WITH_FAST + soap->labidx = 0; + for (;;) + { register int i, k; + register char *s; + if (soap_append_lab(soap, NULL, 2)) + return NULL; + s = soap->labbuf + soap->labidx; + k = 3 * ((soap->lablen - soap->labidx) / 3); + soap->labidx = 3 * (soap->lablen / 3); + if (!s) + return NULL; + for (i = 0; i < k; i += 3) + { register unsigned long m = 0; + register int j = 0; + do + { register soap_wchar c = soap_get(soap); + if (c == '=' || c < 0) + { unsigned char *p; + switch (j) + { case 2: + *s++ = (char)((m >> 4) & 0xFF); + i++; + break; + case 3: + *s++ = (char)((m >> 10) & 0xFF); + *s++ = (char)((m >> 2) & 0xFF); + i += 2; + } + if (n) + *n = (int)(soap->lablen - k + i); + p = (unsigned char*)soap_malloc(soap, soap->lablen - k + i); + if (p) + memcpy(p, soap->labbuf, soap->lablen - k + i); + if (c >= 0) + { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT) + ; + } + soap_unget(soap, c); + return p; + } + c -= '+'; + if (c >= 0 && c <= 79) + { m = (m << 6) + soap_base64i[c]; + j++; + } + } while (j < 4); + *s++ = (char)((m >> 16) & 0xFF); + *s++ = (char)((m >> 8) & 0xFF); + *s++ = (char)(m & 0xFF); + } + } +#else + if (soap_new_block(soap)) + return NULL; + for (;;) + { register int i; + register char *s = (char*)soap_push_block(soap, 3 * SOAP_BLKLEN); /* must be multiple of 3 */ + if (!s) + { soap_end_block(soap); + return NULL; + } + for (i = 0; i < SOAP_BLKLEN; i++) + { register unsigned long m = 0; + register int j = 0; + do + { register soap_wchar c = soap_get(soap); + if (c == '=' || c < 0) + { unsigned char *p; + i *= 3; + switch (j) + { case 2: + *s++ = (char)((m >> 4) & 0xFF); + i++; + break; + case 3: + *s++ = (char)((m >> 10) & 0xFF); + *s++ = (char)((m >> 2) & 0xFF); + i += 2; + } + if (n) + *n = (int)soap_size_block(soap, i); + p = (unsigned char*)soap_save_block(soap, NULL, 0); + if (c >= 0) + { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT) + ; + } + soap_unget(soap, c); + return p; + } + c -= '+'; + if (c >= 0 && c <= 79) + { m = (m << 6) + soap_base64i[c]; + j++; + } + } while (j < 4); + *s++ = (char)((m >> 16) & 0xFF); + *s++ = (char)((m >> 8) & 0xFF); + *s++ = (char)(m & 0xFF); + } + } +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_strdup(struct soap *soap, const char *s) +{ char *t = NULL; + if (s && (t = (char*)soap_malloc(soap, strlen(s) + 1))) + strcpy(t, s); + return t; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_new_block(struct soap *soap) +{ struct soap_blist *p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New block sequence (prev=%p)\n", soap->blist)); + if (!(p = (struct soap_blist*)SOAP_MALLOC(sizeof(struct soap_blist)))) + return SOAP_EOM; + p->next = soap->blist; + p->ptr = NULL; + p->size = 0; + soap->blist = p; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_push_block(struct soap *soap, size_t n) +{ char *p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push block of %u bytes (%u bytes total)\n", (unsigned int)n, (unsigned int)soap->blist->size + (unsigned int)n)); + if (!(p = (char*)SOAP_MALLOC(n + sizeof(char*) + sizeof(size_t)))) + { soap->error = SOAP_EOM; + return NULL; + } + *(char**)p = soap->blist->ptr; + *(size_t*)(p + sizeof(char*)) = n; + soap->blist->ptr = p; + soap->blist->size += n; + return p + sizeof(char*) + sizeof(size_t); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_pop_block(struct soap *soap) +{ char *p; + if (!soap->blist->ptr) + return; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop block\n")); + p = soap->blist->ptr; + soap->blist->size -= *(size_t*)(p + sizeof(char*)); + soap->blist->ptr = *(char**)p; + SOAP_FREE(p); +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static void +soap_update_ptrs(struct soap *soap, char *start, char *end, long offset) +{ int i; + register struct soap_ilist *ip; + register struct soap_flist *fp; + register void *p, **q; + for (i = 0; i < SOAP_IDHASH; i++) + for (ip = soap->iht[i]; ip; ip = ip->next) + { if (ip->ptr && (char*)ip->ptr >= start && (char*)ip->ptr < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", ip->id, ip->ptr, (char*)ip->ptr + offset)); + ip->ptr = (char*)ip->ptr + offset; + } + for (q = &ip->link; q; q = (void**)p) + { p = *q; + if (p && (char*)p >= start && (char*)p < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Link update id='%s' %p\n", ip->id, p)); + *q = (char*)p + offset; + } + } + for (q = &ip->copy; q; q = (void**)p) + { p = *q; + if (p && (char*)p >= start && (char*)p < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy chain update id='%s' %p\n", ip->id, p)); + *q = (char*)p + offset; + } + } + for (fp = ip->flist; fp; fp = fp->next) + { if ((char*)fp->ptr >= start && (char*)fp->ptr < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy list update id='%s' %p\n", ip->id, fp)); + fp->ptr = (char*)fp->ptr + offset; + } + } + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static int +soap_has_copies(struct soap *soap, register const char *start, register const char *end) +{ register int i; + register struct soap_ilist *ip; + register struct soap_flist *fp; + register const char *p; + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { for (p = (const char*)ip->copy; p; p = *(const char**)p) + if (p >= start && p < end) + return SOAP_ERR; + for (fp = ip->flist; fp; fp = fp->next) + if ((const char*)fp->ptr >= start && (const char*)fp->ptr < end) + return SOAP_ERR; + } + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_resolve(struct soap *soap) +{ register int i; + register struct soap_ilist *ip; + register struct soap_flist *fp; + short flag; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data\n")); + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { if (ip->ptr) + { register void *p, **q, *r; + q = (void**)ip->link; + ip->link = NULL; + r = ip->ptr; + DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing link chain to resolve id='%s'\n", ip->id)); + while (q) + { p = *q; + *q = r; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "... link %p -> %p\n", q, r)); + q = (void**)p; + } + } + else if (*ip->id == '#') + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Missing data for id='%s'\n", ip->id)); + strcpy(soap->id, ip->id + 1); + return soap->error = SOAP_MISSING_ID; + } + } + } + do + { flag = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution phase\n")); + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { if (ip->ptr && !soap_has_copies(soap, (const char*)ip->ptr, (const char*)ip->ptr + ip->size)) + { if (ip->copy) + { register void *p, **q = (void**)ip->copy; + DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing copy chain to resolve id='%s'\n", ip->id)); + ip->copy = NULL; + do + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... copy %p -> %p (%u bytes)\n", ip->ptr, q, (unsigned int)ip->size)); + p = *q; + memcpy(q, ip->ptr, ip->size); + q = (void**)p; + } while (q); + flag = 1; + } + for (fp = ip->flist; fp; fp = ip->flist) + { register unsigned int k = fp->level; + register void *p = ip->ptr; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data type=%d location=%p level=%u,%u id='%s'\n", ip->type, p, ip->level, fp->level, ip->id)); + while (ip->level < k) + { register void **q = (void**)soap_malloc(soap, sizeof(void*)); + if (!q) + return soap->error; + *q = p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level, new location=%p holds=%p...\n", q, *q)); + p = (void*)q; + k--; + } + if (fp->fcopy) + fp->fcopy(soap, ip->type, fp->type, fp->ptr, p, ip->size); + else + soap_fcopy(soap, ip->type, fp->type, fp->ptr, p, ip->size); + ip->flist = fp->next; + SOAP_FREE(fp); + flag = 1; + } + } + } + } + } while (flag); +#ifdef SOAP_DEBUG + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { if (ip->copy || ip->flist) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution error: forwarded data for id='%s' could not be propagated, please report this problem to the developers\n", ip->id)); + } + } + } +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution done\n")); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_size_block(struct soap *soap, size_t n) +{ if (soap->blist->ptr) + { soap->blist->size -= *(size_t*)(soap->blist->ptr + sizeof(char*)) - n; + *(size_t*)(soap->blist->ptr + sizeof(char*)) = n; + } + return soap->blist->size; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_first_block(struct soap *soap) +{ char *p, *q, *r; + p = soap->blist->ptr; + if (!p) + return NULL; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "First block\n")); + r = NULL; + do + { q = *(char**)p; + *(char**)p = r; + r = p; + p = q; + } while (p); + soap->blist->ptr = r; + return r + sizeof(char*) + sizeof(size_t); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_next_block(struct soap *soap) +{ char *p; + p = soap->blist->ptr; + if (p) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Next block\n")); + soap->blist->ptr = *(char**)p; + SOAP_FREE(p); + if (soap->blist->ptr) + return soap->blist->ptr + sizeof(char*) + sizeof(size_t); + } + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_block_size(struct soap *soap) +{ return *(size_t*)(soap->blist->ptr + sizeof(char*)); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_end_block(struct soap *soap) +{ struct soap_blist *bp; + char *p, *q; + bp = soap->blist; + if (bp) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of block sequence, free all remaining blocks\n")); + for (p = bp->ptr; p; p = q) + { q = *(char**)p; + SOAP_FREE(p); + } + soap->blist = bp->next; + SOAP_FREE(bp); + } + DBGLOG(TEST, if (soap->blist) SOAP_MESSAGE(fdebug, "Restore previous block sequence\n")); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_save_block(struct soap *soap, char *p, int flag) +{ register size_t n; + register char *q, *s; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Save all blocks in contiguous memory space of %u bytes (%p->%p)\n", (unsigned int)soap->blist->size, soap->blist->ptr, p)); + if (soap->blist->size) + { if (!p) + p = (char*)soap_malloc(soap, soap->blist->size); + if (p) + { for (s = p, q = soap_first_block(soap); q; q = soap_next_block(soap)) + { n = soap_block_size(soap); +#ifndef WITH_NOIDREF + if (flag) + soap_update_ptrs(soap, q, q + n, (long)s - (long)q); /* pointers s and q may or may not be related */ +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy %u bytes from %p to %p\n", (unsigned int)n, q, s)); + memcpy(s, q, n); + s += n; + } + } + else + soap->error = SOAP_EOM; + } + soap_end_block(soap); + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putsize(struct soap *soap, const char *type, int size) +{ return soap_putsizes(soap, type, &size, 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putsizes(struct soap *soap, const char *type, const int *size, int dim) +{ return soap_putsizesoffsets(soap, type, size, NULL, dim); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putsizesoffsets(struct soap *soap, const char *type, const int *size, const int *offset, int dim) +{ int i; + if (!type) + return NULL; + if (soap->version == 2) + { sprintf(soap->type, "%s[%d", type, size[0]); + for (i = 1; i < dim; i++) + sprintf(soap->type + strlen(soap->type), " %d", size[i]); + } + else + { if (offset) + { sprintf(soap->type, "%s[%d", type, size[0] + offset[0]); + for (i = 1; i < dim; i++) + sprintf(soap->type + strlen(soap->type), ",%d", size[i] + offset[i]); + } + else + { sprintf(soap->type, "%s[%d", type, size[0]); + for (i = 1; i < dim; i++) + sprintf(soap->type + strlen(soap->type), ",%d", size[i]); + } + strcat(soap->type, "]"); + } + return soap->type; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putoffset(struct soap *soap, int offset) +{ return soap_putoffsets(soap, &offset, 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putoffsets(struct soap *soap, const int *offset, int dim) +{ register int i; + sprintf(soap->arrayOffset, "[%d", offset[0]); + for (i = 1; i < dim; i++) + sprintf(soap->arrayOffset + strlen(soap->arrayOffset), ",%d", offset[i]); + strcat(soap->arrayOffset, "]"); + return soap->arrayOffset; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_size(const int *size, int dim) +{ register int i, n = size[0]; + for (i = 1; i < dim; i++) + n *= size[i]; + return n; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getoffsets(const char *attr, const int *size, int *offset, int dim) +{ register int i, j = 0; + if (offset) + for (i = 0; i < dim && attr && *attr; i++) + { attr++; + j *= size[i]; + j += offset[i] = (int)atol(attr); + attr = strchr(attr, ','); + } + else + for (i = 0; i < dim && attr && *attr; i++) + { attr++; + j *= size[i]; + j += (int)atol(attr); + attr = strchr(attr, ','); + } + return j; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getsize(const char *attr1, const char *attr2, int *j) +{ register int n, k; + char *s; + *j = 0; + if (!*attr1) + return -1; + n = 1; + do + { attr1++; + k = (int)soap_strtol(attr1, &s, 10); + n *= k; + if (k < 0 || n > SOAP_MAXARRAYSIZE || s == attr1) + return -1; + attr1 = strchr(s, ','); + if (!attr1) + attr1 = strchr(s, ' '); + if (attr2 && *attr2) + { attr2++; + *j *= k; + k = (int)soap_strtol(attr2, &s, 10); + *j += k; + if (k < 0) + return -1; + attr2 = s; + } + } while (attr1 && *attr1 != ']'); + return n - *j; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getsizes(const char *attr, int *size, int dim) +{ register int i, k, n; + if (!*attr) + return -1; + i = strlen(attr); + n = 1; + do + { for (i = i-1; i >= 0; i--) + if (attr[i] == '[' || attr[i] == ',' || attr[i] == ' ') + break; + k = (int)atol(attr + i + 1); + n *= size[--dim] = k; + if (k < 0 || n > SOAP_MAXARRAYSIZE) + return -1; + } while (i >= 0 && attr[i] != '['); + return n; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getposition(const char *attr, int *pos) +{ register int i, n; + if (!*attr) + return -1; + n = 0; + i = 1; + do + { pos[n++] = (int)atol(attr + i); + while (attr[i] && attr[i] != ',' && attr[i] != ']') + i++; + if (attr[i] == ',') + i++; + } while (n < SOAP_MAXDIMS && attr[i] && attr[i] != ']'); + return n; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_push_namespace(struct soap *soap, const char *id, const char *ns) +{ register struct soap_nlist *np; + register struct Namespace *p; + np = (struct soap_nlist*)SOAP_MALLOC(sizeof(struct soap_nlist) + strlen(id)); + if (!np) + return soap->error = SOAP_EOM; + np->next = soap->nlist; + soap->nlist = np; + strcpy(np->id, id); + np->level = soap->level; + np->index = -1; + np->ns = NULL; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push namespace binding (level=%u) '%s' '%s'\n", soap->level, id, ns)); + p = soap->local_namespaces; + if (p) + { register short i = 0; + for (; p->id; p++, i++) + { if (p->ns && !strcmp(ns, p->ns)) + { if (p->out) + { SOAP_FREE(p->out); + p->out = NULL; + } + break; + } + if (p->out) + { if (!SOAP_STRCMP(ns, p->out)) + break; + } + else if (p->in) + { if (!soap_tag_cmp(ns, p->in)) + { if ((p->out = (char*)SOAP_MALLOC(strlen(ns) + 1))) + strcpy(p->out, ns); + break; + } + } + } + if (p && p->id) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push OK ('%s' matches '%s' in namespace table)\n", id, p->id)); + np->index = i; + } + } + if (!p || !p->id) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push NOT OK: no match found for '%s' in namespace mapping table (added to stack anyway)\n", ns)); + np->ns = (char*)SOAP_MALLOC(strlen(ns) + 1); + if (!np->ns) + return soap->error = SOAP_EOM; + strcpy(np->ns, ns); + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_pop_namespace(struct soap *soap) +{ register struct soap_nlist *np; + while (soap->nlist && soap->nlist->level >= soap->level) + { np = soap->nlist->next; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Popped namespace binding (level=%u) '%s'\n", soap->level, soap->nlist->id)); + if (soap->nlist->ns) + SOAP_FREE(soap->nlist->ns); + SOAP_FREE(soap->nlist); + soap->nlist = np; + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_match_namespace(struct soap *soap, const char *id1, const char *id2, int n1, int n2) +{ register struct soap_nlist *np = soap->nlist; + while (np && (strncmp(np->id, id1, n1) || np->id[n1])) + np = np->next; + if (np) + { if (np->index < 0 || (np->index >= 0 && soap->local_namespaces[np->index].id && (strncmp(soap->local_namespaces[np->index].id, id2, n2) || soap->local_namespaces[np->index].id[n2]))) + return SOAP_NAMESPACE; + return SOAP_OK; + } + if (n1 == 3 && n1 == n2 && !strcmp(id1, "xml") && !strcmp(id1, id2)) + return SOAP_OK; + return SOAP_SYNTAX_ERROR; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_tag_cmp(const char *s, const char *t) +{ for (;;) + { register int c1 = *s; + register int c2 = *t; + if (!c1 || c1 == '"') + break; + if (c2 != '-') + { if (c1 != c2) + { if (c1 >= 'A' && c1 <= 'Z') + c1 += 'a' - 'A'; + if (c2 >= 'A' && c2 <= 'Z') + c2 += 'a' - 'A'; + } + if (c1 != c2) + { if (c2 != '*') + return 1; + c2 = *++t; + if (!c2) + return 0; + if (c2 >= 'A' && c2 <= 'Z') + c2 += 'a' - 'A'; + for (;;) + { c1 = *s; + if (!c1 || c1 == '"') + break; + if (c1 >= 'A' && c1 <= 'Z') + c1 += 'a' - 'A'; + if (c1 == c2) + if (!soap_tag_cmp(s + 1, t + 1)) + return 0; + s++; + } + break; + } + } + s++; + t++; + } + if (*t == '*' && !t[1]) + return 0; + return *t; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_match_tag(struct soap *soap, const char *tag1, const char *tag2) +{ register const char *s, *t; + if (!tag1 || !tag2 || !*tag2) + return SOAP_OK; + s = strchr(tag1, ':'); + t = strchr(tag2, ':'); + if (t) + { if (s) + { if (t[1] && SOAP_STRCMP(s + 1, t + 1)) + return SOAP_TAG_MISMATCH; + if (t != tag2 && soap_match_namespace(soap, tag1, tag2, s - tag1, t - tag2)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2)); + return SOAP_TAG_MISMATCH; + } + } + else if (SOAP_STRCMP(tag1, t + 1)) + return SOAP_TAG_MISMATCH; + else if (t != tag2 && soap_match_namespace(soap, tag1, tag2, 0, t - tag2)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2)); + return SOAP_TAG_MISMATCH; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags and (default) namespaces match: '%s' '%s'\n", tag1, tag2)); + return SOAP_OK; + } + if (s) + { if (SOAP_STRCMP(s + 1, tag2)) + return SOAP_TAG_MISMATCH; + } + else if (SOAP_STRCMP(tag1, tag2)) + return SOAP_TAG_MISMATCH; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags match: '%s' '%s'\n", tag1, tag2)); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_match_array(struct soap *soap, const char *type) +{ if (*soap->arrayType) + if (soap_match_tag(soap, soap->arrayType, type) + && soap_match_tag(soap, soap->arrayType, "xsd:anyType") + && soap_match_tag(soap, soap->arrayType, "xsd:ur-type") + ) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array type mismatch: '%s' '%s'\n", soap->arrayType, type)); + return SOAP_TAG_MISMATCH; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ + +#ifdef WITH_OPENSSL +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_ssl_server_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *password, const char *cafile, const char *capath, const char *dhfile, const char *randfile, const char *sid) +{ int err; + soap->keyfile = keyfile; + soap->password = password; + soap->cafile = cafile; + soap->capath = capath; + if (dhfile) + { soap->dhfile = dhfile; + soap->rsa = 0; + } + else + { soap->dhfile = NULL; + soap->rsa = 1; + } + soap->randfile = randfile; + soap->require_client_auth = (flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION); + if (!(err = soap->fsslauth(soap))) + if (sid) + SSL_CTX_set_session_id_context(soap->ctx, (unsigned char*)sid, strlen(sid)); + return err; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_ssl_client_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *password, const char *cafile, const char *capath, const char *randfile) +{ soap->keyfile = keyfile; + soap->password = password; + soap->cafile = cafile; + soap->capath = capath; + soap->dhfile = NULL; + soap->rsa = 0; + soap->randfile = randfile; + soap->require_server_auth = (flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION); + return soap->fsslauth(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +static void +ssl_init() +{ static int done = 0; + if (!done) + { done = 1; + SSL_library_init(); +#ifndef WITH_LEAN + SSL_load_error_strings(); +#endif + if (!RAND_load_file("/dev/urandom", 1024)) + { int r; +#ifdef HAVE_RAND_R + unsigned int s = (unsigned int)time(NULL); +#endif + char buf[SOAP_BUFLEN]; + RAND_seed(buf, sizeof(buf)); + while (!RAND_status()) + { +#ifdef HAVE_RAND_R + r = rand_r(&s); +#else + r = rand(); +#endif + RAND_seed(&r, sizeof(int)); + } + } + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static const char * +ssl_error(struct soap *soap, int ret) +{ int err = SSL_get_error(soap->ssl, ret); + const char *msg = soap_str_code(h_ssl_error_codes, err); + if (msg) + strcpy(soap->msgbuf, msg); + else + return ERR_error_string(err, soap->msgbuf); + if (ERR_peek_error()) + { unsigned long r; + strcat(soap->msgbuf, "\n"); + while ((r = ERR_get_error())) + ERR_error_string_n(r, soap->msgbuf + strlen(soap->msgbuf), sizeof(soap->msgbuf) - strlen(soap->msgbuf)); + } + else + { switch (ret) + { case 0: + strcpy(soap->msgbuf, "EOF was observed that violates the protocol. The client probably provided invalid authentication information."); + break; + case -1: + sprintf(soap->msgbuf, "Error observed by underlying BIO: %s", strerror(errno)); + break; + } + } + return soap->msgbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +ssl_password(char *buf, int num, int rwflag, void *userdata) +{ if (num < (int)strlen((char*)userdata) + 1) + return 0; + return strlen(strcpy(buf, (char*)userdata)); +} +#endif + +/******************************************************************************/ +/* This callback is included for future references. It should not be deleted +#ifndef PALM_2 +static DH * +ssl_tmp_dh(SSL *ssl, int is_export, int keylength) +{ static DH *dh512 = NULL; + static DH *dh1024 = NULL; + DH *dh; + switch (keylength) + { case 512: + if (!dh512) + { BIO *bio = BIO_new_file("dh512.pem", "r"); + if (bio) + { dh512 = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + return dh512; + } + } + else + return dh512; + default: + if (!dh1024) + { BIO *bio = BIO_new_file("dh1024.pem", "r"); + if (bio) + { dh1024 = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + } + } + dh = dh1024; + } + return dh; +} +#endif +*/ +/******************************************************************************/ +#ifndef PALM_1 +static int +ssl_auth_init(struct soap *soap) +{ ssl_init(); + if (!soap->ctx) + if (!(soap->ctx = SSL_CTX_new(SSLv23_method()))) + return soap_set_receiver_error(soap, "SSL error", "Can't setup context", SOAP_SSL_ERROR); + if (soap->randfile) + { if (!RAND_load_file(soap->randfile, -1)) + return soap_set_receiver_error(soap, "SSL error", "Can't load randomness", SOAP_SSL_ERROR); + } + if (soap->cafile || soap->capath) + if (!SSL_CTX_load_verify_locations(soap->ctx, soap->cafile, soap->capath)) + return soap_set_receiver_error(soap, "SSL error", "Can't read CA file and/or directory", SOAP_SSL_ERROR); + if (!SSL_CTX_set_default_verify_paths(soap->ctx)) + return soap_set_receiver_error(soap, "SSL error", "Can't read default CA file and/or directory", SOAP_SSL_ERROR); + if (soap->keyfile) + { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile)) + return soap_set_receiver_error(soap, "SSL error", "Can't read certificate key file", SOAP_SSL_ERROR); + if (soap->password) + { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password); + SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password); + if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM)) + return soap_set_receiver_error(soap, "SSL error", "Can't read key file", SOAP_SSL_ERROR); + } + } + if (soap->rsa) + { RSA *rsa = RSA_generate_key(512, RSA_F4, NULL, NULL); + if (!SSL_CTX_set_tmp_rsa(soap->ctx, rsa)) + { if (rsa) + RSA_free(rsa); + return soap_set_receiver_error(soap, "SSL error", "Can't set RSA key", SOAP_SSL_ERROR); + } + RSA_free(rsa); + } + else if (soap->dhfile) + { DH *dh = 0; + BIO *bio; + bio = BIO_new_file(soap->dhfile, "r"); + if (!bio) + return soap_set_receiver_error(soap, "SSL error", "Can't read DH file", SOAP_SSL_ERROR); + dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + if (SSL_CTX_set_tmp_dh(soap->ctx, dh) < 0) + { if (dh) + DH_free(dh); + return soap_set_receiver_error(soap, "SSL error", "Can't set DH parameters", SOAP_SSL_ERROR); + } + DH_free(dh); + } + SSL_CTX_set_options(soap->ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2); + SSL_CTX_set_verify(soap->ctx, soap->require_client_auth ? (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT) : soap->require_server_auth ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, soap->fsslverify); +#if (OPENSSL_VERSION_NUMBER < 0x00905100L) + SSL_CTX_set_verify_depth(soap->ctx, 1); +#else + SSL_CTX_set_verify_depth(soap->ctx, 9); +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +ssl_verify_callback(int ok, X509_STORE_CTX *store) +{ +#ifdef SOAP_DEBUG + if (!ok) + { char data[256]; + X509 *cert = X509_STORE_CTX_get_current_cert(store); + fprintf(stderr, "SSL Verify error with certificate at depth %d: %s\n", X509_STORE_CTX_get_error_depth(store), X509_verify_cert_error_string(X509_STORE_CTX_get_error(store))); + X509_NAME_oneline(X509_get_issuer_name(cert), data, sizeof(data)); + fprintf(stderr, "certificate issuer %s\n", data); + X509_NAME_oneline(X509_get_subject_name(cert), data, sizeof(data)); + fprintf(stderr, "certificate subject %s\n", data); + } +#endif + /* return 1 to always continue, but unsafe progress will be terminated by SSL */ + return ok; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_ssl_accept(struct soap *soap) +{ int i, r; + if (!soap_valid_socket(soap->socket)) + return soap_set_receiver_error(soap, "SSL error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR); + if (!soap->ssl) + { soap->ssl = SSL_new(soap->ctx); + if (!soap->ssl) + return soap_set_receiver_error(soap, "SSL error", "SSL_new() failed in soap_ssl_accept()", SOAP_SSL_ERROR); + } + else + SSL_clear(soap->ssl); + soap->imode |= SOAP_ENC_SSL; + soap->omode |= SOAP_ENC_SSL; +#ifdef WIN32 + { u_long nonblocking = 1; + ioctlsocket((SOAP_SOCKET)soap->socket, FIONBIO, &nonblocking); + } +#else + fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL)|O_NONBLOCK); +#endif + soap->bio = BIO_new_socket((SOAP_SOCKET)soap->socket, BIO_NOCLOSE); + SSL_set_bio(soap->ssl, soap->bio, soap->bio); + i = 100; /* 100 * 0.1 ms retries */ + while ((r = SSL_accept(soap->ssl)) <= 0) + { int err = SSL_get_error(soap->ssl, r); + if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) + { struct timeval timeout; + fd_set fd; + if (i-- <= 0) + break; + timeout.tv_sec = 0; + timeout.tv_usec = 100000; + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->socket, &fd); + r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout); + if (r < 0 && soap_socket_errno != SOAP_EINTR) + { soap->errnum = soap_socket_errno; + return SOAP_EOF; + } + } + else + { soap->errnum = err; + break; + } + } +#ifdef WIN32 + { u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)soap->socket, FIONBIO, &blocking); + } +#else + fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL)&~O_NONBLOCK); +#endif + if (r <= 0) + { soap_set_receiver_error(soap, ssl_error(soap, r), "SSL_accept() failed in soap_ssl_accept()", SOAP_SSL_ERROR); + soap_closesock(soap); + return SOAP_SSL_ERROR; + } + if (soap->require_client_auth) + { X509 *peer; + int err; + if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK) + { soap_closesock(soap); + return soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL certificate presented by peer cannot be verified in soap_ssl_accept()", SOAP_SSL_ERROR); + } + peer = SSL_get_peer_certificate(soap->ssl); + if (!peer) + { soap_closesock(soap); + return soap_set_sender_error(soap, "SSL error", "No SSL certificate was presented by the peer in soap_ssl_accept()", SOAP_SSL_ERROR); + } + X509_free(peer); + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#endif /* WITH_OPENSSL */ + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_init(struct soap *soap) +{ soap->errmode = 1; +#ifdef WIN32 + if (tcp_done) + return 0; + else + { WSADATA w; + if (WSAStartup(MAKEWORD(1, 1), &w)) + return -1; + tcp_done = 1; + } +#endif + return 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_done(struct soap *soap) +{ +#ifdef SOAP_DEBUG + int i; +#endif + soap_free(soap); + while (soap->clist) + { struct soap_clist *p = soap->clist->next; + SOAP_FREE(soap->clist); + soap->clist = p; + } + soap->keep_alive = 0; /* to force close the socket */ + soap_closesock(soap); +#ifdef WITH_COOKIES + soap_free_cookies(soap); +#endif + while (soap->plugins) + { register struct soap_plugin *p = soap->plugins->next; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Removing plugin '%s'\n", soap->plugins->id)); + if (soap->plugins->fcopy || !soap->copy) + soap->plugins->fdelete(soap, soap->plugins); + SOAP_FREE(soap->plugins); + soap->plugins = p; + } + soap->fplugin = fplugin; +#ifndef WITH_NOHTTP + soap->fpost = http_post; + soap->fget = http_get; + soap->fposthdr = http_post_header; + soap->fresponse = http_response; + soap->fparse = http_parse; + soap->fparsehdr = http_parse_header; +#endif +#ifndef WITH_NOIO +#ifndef WITH_IPV6 + soap->fresolve = tcp_gethost; +#else + soap->fresolve = NULL; +#endif + soap->faccept = tcp_accept; + soap->fopen = tcp_connect; + soap->fclose = tcp_disconnect; + soap->fclosesocket = tcp_closesocket; + soap->fshutdownsocket = tcp_shutdownsocket; + soap->fsend = fsend; + soap->frecv = frecv; + soap->fpoll = soap_poll; +#else + soap->fopen = NULL; + soap->fclose = NULL; + soap->fpoll = NULL; +#endif +#ifndef WITH_LEANER + soap->fprepareinit = NULL; + soap->fpreparesend = NULL; + soap->fpreparerecv = NULL; +#endif + soap->fignore = NULL; + soap->fserveloop = NULL; +#ifdef WITH_OPENSSL + if (soap->session) + { SSL_SESSION_free(soap->session); + soap->session = NULL; + } +#endif + if (!soap->copy) + { if (soap_valid_socket(soap->master)) + { soap->fclosesocket(soap, (SOAP_SOCKET)soap->master); + soap->master = SOAP_INVALID_SOCKET; + } +#ifdef WITH_OPENSSL + if (soap->ctx) + { SSL_CTX_free(soap->ctx); + soap->ctx = NULL; + } +#endif + } +#ifdef SOAP_DEBUG + for (i = 0; i < SOAP_MAXLOGS; i++) + { soap_close_logfile(soap, i); + if (soap->logfile[i]) + { SOAP_FREE((void*)soap->logfile[i]); + soap->logfile[i] = NULL; + } + } +#endif +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_cleanup(struct soap *soap) +{ soap_done(soap); +#ifdef WIN32 + if (!tcp_done) + return; + tcp_done = 0; + WSACleanup(); +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static const char* +tcp_error(struct soap *soap) +{ register const char *msg = NULL; + switch (soap->errmode) + { case 0: + msg = soap_strerror(soap); + break; + case 1: + msg = "WSAStartup failed"; + break; + case 2: + { +#ifndef WITH_LEAN + msg = soap_str_code(h_error_codes, soap->errnum); + if (!msg) +#endif + { sprintf(soap->msgbuf, "TCP error %d", soap->errnum); + msg = soap->msgbuf; + } + } + } + return msg; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static const char* +http_error(struct soap *soap, int status) +{ register const char *msg = SOAP_STR_EOS; +#ifndef WITH_LEAN + msg = soap_str_code(h_http_error_codes, status); + if (!msg) + msg = SOAP_STR_EOS; +#endif + return msg; +} +#endif +#endif + +/******************************************************************************/ +/* WR[ */ +#ifndef WITH_IPV6 +/* ]WR */ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_gethost(struct soap *soap, const char *addr, struct in_addr *inaddr) +{ unsigned long iadd; + struct hostent hostent, *host = &hostent; +/* WR[ */ +#ifdef VXWORKS + int hostint; + char *addrcopy = (char*)malloc(strlen(addr) + 1); /*copy of addr. */ + /* inet_addr(), and hostGetByName() expect "char *"; addr is a "const char *". */ + strncpy(addrcopy, addr, strlen(addr)+1); + iadd = inet_addr(addrcopy); +#else +/* ]WR */ +#if defined(_AIXVERSION_431) || defined(TRU64) + struct hostent_data ht_data; +#endif + iadd = inet_addr(addr); +/* WR[ */ +#endif +/* ]WR */ + if ((int)iadd != -1) + { memcpy(inaddr, &iadd, sizeof(iadd)); +/* WR[ */ +#ifdef VXWORKS + free(addrcopy); +#endif +/* ]WR */ + return SOAP_OK; + } +#if defined(__GLIBC__) + if (gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &host, &soap->errnum) < 0) + host = NULL; +#elif defined(_AIXVERSION_431) || defined(TRU64) + memset((void*)&ht_data, 0, sizeof(ht_data)); + if (gethostbyname_r(addr, &hostent, &ht_data) < 0) + { host = NULL; + soap->errnum = h_errno; + } +#elif defined(HAVE_GETHOSTBYNAME_R) + host = gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &soap->errnum); +/* WR[ */ +#elif defined(VXWORKS) + /* If the DNS resolver library resolvLib has been configured in the vxWorks + * image, a query for the host IP address is sent to the DNS server, if the + * name was not found in the local host table. */ + hostint = hostGetByName(addrcopy); + if (hostint == ERROR) + { host = NULL; + soap->errnum = soap_errno; + } + free(addrcopy); /*free() is placed after the error checking to assure that + * errno captured is that from hostGetByName() */ +/* ]WR */ +#else + if (!(host = gethostbyname(addr))) + soap->errnum = h_errno; +#endif + if (!host) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Host name not found\n")); + return SOAP_ERR; + } +/* WR[ */ +#ifdef VXWORKS + inaddr->s_addr = hostint; +#else +/* ]WR */ + memcpy(inaddr, host->h_addr, host->h_length); +/* WR[ */ +#endif +/* ]WR */ + return SOAP_OK; +} +#endif +#endif +/* WR[ */ +#endif /* WITH_IPV6 */ +/* ]WR */ + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_connect(struct soap *soap, const char *endpoint, const char *host, int port) +{ struct sockaddr_in sockaddr; +/* WR[ */ +#ifdef WITH_IPV6 + struct addrinfo *addrinfo; + struct addrinfo hints; + struct addrinfo resaddr; + struct sockaddr_storage addrstorage; + int err; +#endif /* WITH_IPV6 */ +/* ]WR */ + register int fd; +#ifndef WITH_LEAN + int len = SOAP_BUFLEN; + int set = 1; +#endif + if (soap_valid_socket(soap->socket)) + soap->fclosesocket(soap, (SOAP_SOCKET)soap->socket); + soap->socket = SOAP_INVALID_SOCKET; + if (tcp_init(soap)) + { soap_set_sender_error(soap, tcp_error(soap), "TCP initialization failed in tcp_connect()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + soap->errmode = 0; +/* WR[ */ +#ifdef WITH_IPV6 + memset((void*)&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + soap->errmode = 2; + if (soap->proxy_host) + err = getaddrinfo(soap->proxy_host, soap_int2s(soap, soap->proxy_port), &hints, &addrinfo); + else + err = getaddrinfo(host, soap_int2s(soap, port), &hints, &addrinfo); + if (addrinfo) + { resaddr = *addrinfo; + addrstorage = *((struct sockaddr_storage*)addrinfo->ai_addr); + resaddr.ai_addr = (struct sockaddr*)&addrstorage; + freeaddrinfo(addrinfo); + } + if (err) + { soap_set_sender_error(soap, gai_strerror(err), "TCP getaddrinfo on proxy host failed in tcp_connect()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + fd = (int)socket(resaddr.ai_family, resaddr.ai_socktype, resaddr.ai_protocol); /* modified to use fd */ + soap->errmode = 0; +#else /* WITH_IPV6 */ +/* ]WR */ + fd = (int)socket(AF_INET, SOCK_STREAM, 0); +/* WR[ */ +#endif /* WITH_IPV6 */ +/* ]WR */ + if (fd < 0) + { soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "TCP socket failed in tcp_connect()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#ifdef SOCKET_CLOSE_ON_EXEC +#ifdef WIN32 +#ifndef UNDER_CE + SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0); +#endif +#else + fcntl (fd, F_SETFD, 1); +#endif +#endif +#ifndef WITH_LEAN + if (soap->connect_flags & SO_LINGER) + { struct linger linger; + memset((void*)&linger, 0, sizeof(linger)); + linger.l_onoff = 1; + linger.l_linger = 0; + if (setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger))) + { soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "TCP setsockopt SO_LINGER failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + } + if ((soap->connect_flags & ~SO_LINGER) && setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, soap->connect_flags & ~SO_LINGER, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "TCP setsockopt failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + if (soap->keep_alive && setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "TCP setsockopt SO_KEEPALIVE failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + if (setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "TCP setsockopt SO_SNDBUF failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + if (setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "TCP setsockopt SO_RCVBUF failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } +#ifdef TCP_NODELAY + if (setsockopt((SOAP_SOCKET)fd, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "TCP setsockopt TCP_NODELAY failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } +#endif +#endif +/* WR[ */ +#ifndef WITH_IPV6 +/* ]WR */ + memset((void*)&sockaddr, 0, sizeof(sockaddr)); + sockaddr.sin_family = AF_INET; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Open socket %d to host='%s'\n", fd, host)); + soap->errmode = 2; + if (soap->proxy_host) + { if (soap->fresolve(soap, soap->proxy_host, &sockaddr.sin_addr)) + { soap_set_sender_error(soap, tcp_error(soap), "TCP get proxy host by name failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + sockaddr.sin_port = htons((short)soap->proxy_port); + } + else + { if (soap->fresolve(soap, host, &sockaddr.sin_addr)) + { soap_set_sender_error(soap, tcp_error(soap), "TCP get host by name failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + sockaddr.sin_port = htons((short)port); + } + soap->errmode = 0; +/* WR[ */ +#endif /* WITH_IPV6 */ +/* ]WR */ +#ifndef WITH_LEAN + if (soap->connect_timeout) +#if defined(WIN32) + { u_long nonblocking = 1; + ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &nonblocking); + } +/* WR[ */ +#elif defined(VXWORKS) + { vx_nonblocking = TRUE; + ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&vx_nonblocking)); /* modified to use fd */ + } +/* ]WR */ +#else + fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)|O_NONBLOCK); +#endif + else +#if defined(WIN32) + { u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &blocking); + } +/* WR[ */ +#elif defined(VXWORKS) + { vx_nonblocking = FALSE; + ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&vx_nonblocking)); /* modified to use fd */ + } +/* ]WR */ +#else + fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)&~O_NONBLOCK); +#endif +#endif + for (;;) + { +/* WR[ */ +#ifdef WITH_IPV6 + if (connect((SOAP_SOCKET)fd, resaddr.ai_addr, resaddr.ai_addrlen)) /* modified to use fd */ +#else /* WITH_IPV6 */ + if (connect((SOAP_SOCKET)fd, (struct sockaddr*)&sockaddr, sizeof(sockaddr))) +#endif /* WITH_IPV6 */ +/* ]WR */ + { +#ifndef WITH_LEAN + if (soap->connect_timeout && (soap_socket_errno == SOAP_EINPROGRESS || soap_socket_errno == SOAP_EWOULDBLOCK)) + { struct timeval timeout; +#if defined(SOCKLEN_T) + SOCKLEN_T n = sizeof(struct sockaddr_in); +#elif defined(__socklen_t_defined) || defined(_SOCKLEN_T) || defined(CYGWIN) + socklen_t n = sizeof(struct sockaddr_in); +#elif defined(WIN32) || defined(__APPLE__) || defined(HP_UX) || defined(SUN_OS) || defined(OPENSERVER) || defined(TRU64) || defined(VXWORKS) + int n = sizeof(struct sockaddr_in); +#else + size_t n = sizeof(struct sockaddr_in); +#endif + fd_set fds; + if (soap->connect_timeout > 0) + { timeout.tv_sec = soap->connect_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->connect_timeout/1000000; + timeout.tv_usec = -soap->connect_timeout%1000000; + } + FD_ZERO(&fds); + FD_SET((SOAP_SOCKET)fd, &fds); + for (;;) + { int r = select((SOAP_SOCKET)(fd + 1), NULL, &fds, NULL, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n")); + soap_set_sender_error(soap, "Timeout", "TCP connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + if (soap_socket_errno != SOAP_EINTR) + { soap->errnum = soap_socket_errno; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); + soap_set_sender_error(soap, tcp_error(soap), "TCP connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + } + n = sizeof(soap->errnum); + if (!getsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_ERROR, (char*)&soap->errnum, &n) && !soap->errnum) + break; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); + soap_set_sender_error(soap, tcp_error(soap), "TCP connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + else +#endif + if (soap_socket_errno != SOAP_EINTR) + { soap->errnum = soap_socket_errno; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); + soap_set_sender_error(soap, tcp_error(soap), "TCP connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + } + else + break; + } +#ifndef WITH_LEAN + if (soap->connect_timeout) +#if defined(WIN32) + { u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &blocking); + } +/* WR[ */ +#elif defined(VXWORKS) + { vx_nonblocking = FALSE; + ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&vx_nonblocking)); /* modified to use fd */ + } +/* ]WR */ +#else + fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)&~O_NONBLOCK); +#endif +#endif + soap->socket = fd; +#ifdef WITH_OPENSSL + soap->imode &= ~SOAP_ENC_SSL; + soap->omode &= ~SOAP_ENC_SSL; + if (!strncmp(endpoint, "https:", 6)) + { int r; + if (soap->proxy_host) + { unsigned int k = soap->omode; /* make sure we only parse HTTP */ + size_t n = soap->count; /* save the content length */ + soap->omode &= ~SOAP_ENC; /* mask IO and ENC */ + soap->omode |= SOAP_IO_BUFFER; + soap_begin_send(soap); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connecting to proxy server\n")); + sprintf(soap->tmpbuf, "CONNECT %s:%d HTTP/%s", host, port, soap->http_version); + if ((soap->error = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return SOAP_INVALID_SOCKET; +#ifndef WITH_LEAN + if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761) + { sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd); + strcpy(soap->tmpbuf, "Basic "); + soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, strlen(soap->tmpbuf + 262)); + if ((soap->error = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf))) + return soap->error; + } +#endif + if ((soap->error = soap->fposthdr(soap, NULL, NULL)) + || soap_flush(soap)) + return SOAP_INVALID_SOCKET; + soap->omode = k; + k = soap->imode; + soap->imode &= ~SOAP_ENC; /* mask IO and ENC */ + if (soap_begin_recv(soap)) + return SOAP_INVALID_SOCKET; + soap->imode = k; + soap->count = n; + soap_begin_send(soap); + } + if (!soap->ctx && (soap->error = soap->fsslauth(soap))) + { soap_set_sender_error(soap, "SSL error", "SSL authentication failed in tcp_connect(): check password, key file, and ca file.", SOAP_SSL_ERROR); + return SOAP_INVALID_SOCKET; + } + soap->ssl = SSL_new(soap->ctx); + if (!soap->ssl) + { soap->error = SOAP_SSL_ERROR; + return SOAP_INVALID_SOCKET; + } + if (soap->session) + { if (!strcmp(soap->session_host, host) && soap->session_port == port) + SSL_set_session(soap->ssl, soap->session); + SSL_SESSION_free(soap->session); + soap->session = NULL; + } + soap->imode |= SOAP_ENC_SSL; + soap->omode |= SOAP_ENC_SSL; + soap->bio = BIO_new_socket((SOAP_SOCKET)fd, BIO_NOCLOSE); + SSL_set_bio(soap->ssl, soap->bio, soap->bio); +#ifndef WITH_LEAN + if (soap->connect_timeout) +#ifdef WIN32 + { u_long nonblocking = 1; + ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &nonblocking); + } +#else + fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)|O_NONBLOCK); +#endif +#endif + for (;;) + { if ((r = SSL_connect(soap->ssl)) <= 0) + { int err = SSL_get_error(soap->ssl, r); + if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) + { soap_set_sender_error(soap, ssl_error(soap, r), "SSL connect failed in tcp_connect()", SOAP_SSL_ERROR); + return SOAP_INVALID_SOCKET; + } + if (soap->connect_timeout) + { struct timeval timeout; + fd_set fds; + if (soap->connect_timeout > 0) + { timeout.tv_sec = soap->connect_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->connect_timeout/1000000; + timeout.tv_usec = -soap->connect_timeout%1000000; + } + FD_ZERO(&fds); + FD_SET((SOAP_SOCKET)(soap->socket), &fds); + for (;;) + { int r = select((SOAP_SOCKET)(soap->socket + 1), &fds, NULL, &fds, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n")); + soap_set_sender_error(soap, "Timeout", "TCP connect failed in tcp_connect()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + } + continue; + } + } + break; + } +#ifndef WITH_LEAN + if (soap->connect_timeout) +#ifdef WIN32 + { u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &blocking); + } +#else + fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)&~O_NONBLOCK); +#endif +#endif + if (soap->require_server_auth) + { X509 *peer; + int err; + if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK) + { soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL certificate presented by peer cannot be verified in tcp_connect()", SOAP_SSL_ERROR); + return SOAP_INVALID_SOCKET; + } + peer = SSL_get_peer_certificate(soap->ssl); + if (!peer) + { soap_set_sender_error(soap, "SSL error", "No SSL certificate was presented by the peer in tcp_connect()", SOAP_SSL_ERROR); + return SOAP_INVALID_SOCKET; + } + X509_NAME_get_text_by_NID(X509_get_subject_name(peer), NID_commonName, soap->msgbuf, sizeof(soap->msgbuf)); + X509_free(peer); + if (soap_tag_cmp(soap->msgbuf, host)) + { soap_set_sender_error(soap, "SSL error", "SSL certificate host name mismatch in tcp_connect()", SOAP_SSL_ERROR); + return SOAP_INVALID_SOCKET; + } + } + } +#endif + return fd; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_bind(struct soap *soap, const char *host, int port, int backlog) +{ struct sockaddr_in sockaddr; +/* WR[ */ +#ifdef WITH_IPV6 + struct addrinfo *addrinfo; + struct addrinfo hints; + struct addrinfo resaddr; + struct sockaddr_storage addrstorage; + int err; +#endif /* WITH_IPV6 */ +/* ]WR */ +#ifndef WITH_LEAN + int len = SOAP_BUFLEN; + int set = 1; +#endif + if (soap_valid_socket(soap->master)) + { soap->fclosesocket(soap, (SOAP_SOCKET)soap->master); + soap->master = SOAP_INVALID_SOCKET; + } + soap->socket = SOAP_INVALID_SOCKET; + soap->errmode = 1; + if (tcp_init(soap)) + { soap_set_receiver_error(soap, tcp_error(soap), "TCP init failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +/* WR[ */ +#ifdef WITH_IPV6 + memset((void*)&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + soap->errmode = 2; + if (host) + err = getaddrinfo(host, soap_int2s(soap, port), &hints, &addrinfo); + else + err = getaddrinfo(NULL, soap_int2s(soap, port), &hints, &addrinfo); + if (NULL != addrinfo) + { + resaddr = *addrinfo; + addrstorage = *((struct sockaddr_storage *) addrinfo->ai_addr); + resaddr.ai_addr = (struct sockaddr *) &addrstorage; + freeaddrinfo(addrinfo); + } + if (err) + { soap_set_receiver_error(soap, gai_strerror(err), "TCP getaddrinfo failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + soap->errmode = 0; + if ((soap->master = socket(resaddr.ai_family, resaddr.ai_socktype, resaddr.ai_protocol)) < 0) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP socket failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#else /* WITH_IPV6 */ +/* ]WR */ + soap->errmode = 0; + if ((soap->master = (int)socket(AF_INET, SOCK_STREAM, 0)) < 0) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP socket failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +/* WR[ */ +#endif /* WITH_IPV6 */ +/* ]WR */ +#ifdef SOCKET_CLOSE_ON_EXEC +#ifdef WIN32 +#ifndef UNDER_CE + SetHandleInformation((HANDLE)soap->master, HANDLE_FLAG_INHERIT, 0); +#endif +#else + fcntl (soap->master, F_SETFD, 1); +#endif +#endif +#ifndef WITH_LEAN + if (soap->bind_flags && setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, soap->bind_flags, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + if (soap->keep_alive && setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt SO_KEEPALIVE failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + if (setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt SO_SNDBUF failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + if (setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt SO_RCVBUF failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#ifdef TCP_NODELAY + if (setsockopt((SOAP_SOCKET)soap->master, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt TCP_NODELAY failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#endif +#endif +/* WR[ */ +#ifdef WITH_IPV6 + soap->errmode = 0; + if (bind(soap->master, resaddr.ai_addr, resaddr.ai_addrlen) || listen(soap->master, backlog)) + { + soap->errnum = soap_socket_errno; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n")); + soap_closesock(soap); + soap_set_receiver_error(soap, tcp_error(soap), "TCP bind failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#else /* WITH_IPV6 */ +/* ]WR */ + memset((void*)&sockaddr, 0, sizeof(sockaddr)); + sockaddr.sin_family = AF_INET; + soap->errmode = 2; + if (host) + { if (soap->fresolve(soap, host, &sockaddr.sin_addr)) + { soap_set_receiver_error(soap, tcp_error(soap), "TCP get host by name failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + } + else + sockaddr.sin_addr.s_addr = htonl(INADDR_ANY); + sockaddr.sin_port = htons((short)port); + soap->errmode = 0; + if (bind((SOAP_SOCKET)soap->master, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) || listen((SOAP_SOCKET)soap->master, backlog)) + { soap->errnum = soap_socket_errno; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n")); + soap_closesock(soap); + soap_set_receiver_error(soap, tcp_error(soap), "TCP bind failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +/* WR[ */ +#endif /* WITH_IPV6 */ +/* ]WR */ +#ifdef WITH_OPENSSL + if (!soap->ctx && (soap->error = soap->fsslauth(soap))) + return SOAP_INVALID_SOCKET; +#endif + return soap->master; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_poll(struct soap *soap) +{ +#ifndef WITH_LEAN + struct timeval timeout; + fd_set sfd, rfd, xfd; + int r; + timeout.tv_sec = 0; + timeout.tv_usec = 0; + FD_ZERO(&rfd); + FD_ZERO(&sfd); + FD_ZERO(&xfd); + if (soap_valid_socket(soap->socket)) + { FD_SET(soap->socket, &rfd); + FD_SET(soap->socket, &sfd); + FD_SET(soap->socket, &xfd); + r = select(soap->socket + 1, &rfd, &sfd, &xfd, &timeout); + if (r > 0 && FD_ISSET(soap->socket, &xfd)) + r = -1; + } + else if (soap_valid_socket(soap->master)) + { FD_SET(soap->master, &rfd); + r = select(soap->master + 1, &rfd, &sfd, NULL, &timeout); + } + else + return SOAP_OK; + if (r > 0) + { +#ifdef WITH_OPENSSL + if (soap->ssl) + { if (soap_valid_socket(soap->socket) && FD_ISSET(soap->socket, &rfd)) + { char buf = '\0'; + if (SSL_peek(soap->ssl, &buf, 1) <= 0) + return SOAP_EOF; + } + } +#endif + if (soap_valid_socket(soap->socket) && FD_ISSET(soap->socket, &rfd)) + return SOAP_EOF; + return SOAP_OK; + } + if (r < 0 && (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) && soap_socket_errno != SOAP_EINTR) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "select failed in soap_poll()", SOAP_TCP_ERROR); + return soap->error = SOAP_TCP_ERROR; + } + else + soap->errnum = soap_errno; + return SOAP_EOF; +#else + return SOAP_OK; +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_accept(struct soap *soap, int s, struct sockaddr *a, int *n) +{ int fd; +#if defined(SOCKLEN_T) + fd = (int)accept((SOAP_SOCKET)s, a, (SOCKLEN_T*)n); +#elif defined(__socklen_t_defined) || defined(_SOCKLEN_T) || defined(CYGWIN) + fd = (int)accept((SOAP_SOCKET)s, a, (socklen_t*)n); +#elif defined(WIN32) || defined(__APPLE__) || defined(HP_UX) || defined(SUN_OS) || defined(OPENSERVER) || defined(TRU64) || defined(VXWORKS) + fd = (int)accept((SOAP_SOCKET)s, a, n); +#else + fd = (int)accept((SOAP_SOCKET)s, a, (size_t*)n); +#endif +#ifdef SOCKET_CLOSE_ON_EXEC +#ifdef WIN32 +#ifndef UNDER_CE + SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0); +#endif +#else + fcntl(fd, F_SETFD, FD_CLOEXEC); +#endif +#endif + return fd; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_accept(struct soap *soap) +{ +/* WR[ */ +#ifdef WITH_IPV6 + struct sockaddr_storage sockaddr; +#else /* WITH_IPV6 */ +/* ]WR */ + struct sockaddr_in sockaddr; +/* WR[ */ +#endif +/* ]WR */ + int n = (int)sizeof(sockaddr); +#ifndef WITH_LEAN + int len = SOAP_BUFLEN; + int set = 1; +#endif + soap->error = SOAP_OK; + memset((void*)&sockaddr, 0, sizeof(sockaddr)); + soap->socket = SOAP_INVALID_SOCKET; + soap->errmode = 0; + if (soap_valid_socket(soap->master)) + { for (;;) + { +#ifndef WITH_LEAN + if (soap->accept_timeout) + { struct timeval timeout; + fd_set fd; + if (soap->accept_timeout > 0) + { timeout.tv_sec = soap->accept_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->accept_timeout/1000000; + timeout.tv_usec = -soap->accept_timeout%1000000; + } + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->master, &fd); + for (;;) + { int r = select((SOAP_SOCKET)(soap->master + 1), &fd, &fd, NULL, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + soap_set_receiver_error(soap, "Timeout", "TCP accept failed in soap_accept()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + if (soap_socket_errno != SOAP_EINTR) + { soap->errnum = soap_socket_errno; + soap_closesock(soap); + soap_set_sender_error(soap, tcp_error(soap), "TCP accept failed in soap_accept()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + } +#if defined(WIN32) + { u_long nonblocking = 1; + ioctlsocket((SOAP_SOCKET)soap->master, FIONBIO, &nonblocking); + } +#elif defined(VXWORKS) + { vx_nonblocking = TRUE; + ioctl((SOAP_SOCKET)soap->master, FIONBIO, (int)(&vx_nonblocking)); + } +#else + fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL)|O_NONBLOCK); +#endif + } + else +#if defined(WIN32) + { u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)soap->master, FIONBIO, &blocking); + } +/* WR[ */ +#elif defined(VXWORKS) + { vx_nonblocking = FALSE; + ioctl((SOAP_SOCKET)soap->master, FIONBIO, (int)(&vx_nonblocking)); + } +/* ]WR */ +#else + fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL)&~O_NONBLOCK); +#endif +#endif + soap->socket = soap->faccept(soap, soap->master, (struct sockaddr*)&sockaddr, &n); + if (soap_valid_socket(soap->socket)) + { +/* WR[ */ +#ifdef WITH_IPV6 +/* Use soap->host to store the numeric form of the remote host */ + getnameinfo((struct sockaddr*)&sockaddr, n, soap->host, sizeof(soap->host), NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket %d from %s\n", soap->socket, soap->host)); + soap->ip = 0; /* info stored in soap->host */ + soap->port = 0; /* info stored in soap->host */ +#else /* WITH_IPV6 */ +/* ]WR */ + soap->ip = ntohl(sockaddr.sin_addr.s_addr); + soap->port = (int)ntohs(sockaddr.sin_port); /* does not return port number on some systems */ + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket %d at port %d from IP %d.%d.%d.%d\n", soap->socket, soap->port, (int)(soap->ip>>24)&0xFF, (int)(soap->ip>>16)&0xFF, (int)(soap->ip>>8)&0xFF, (int)soap->ip&0xFF)); +/* WR[ */ +#endif /* WITH_IPV6 */ +/* ]WR */ + soap->keep_alive = ((soap->imode & SOAP_IO_KEEPALIVE) != 0); +#ifndef WITH_LEAN + if (soap->accept_flags & SO_LINGER) + { struct linger linger; + memset((void*)&linger, 0, sizeof(linger)); + linger.l_onoff = 1; + linger.l_linger = 0; + if (setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt SO_LINGER failed in soap_accept()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + } + if ((soap->accept_flags & ~SO_LINGER) && setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, soap->accept_flags & ~SO_LINGER, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt failed in soap_accept()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + if (soap->keep_alive && setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt SO_KEEPALIVE failed in soap_accept()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + if (setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt SO_SNDBUF failed in soap_accept()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + if (setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt SO_RCVBUF failed in soap_accept()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#ifdef TCP_NODELAY + if (setsockopt((SOAP_SOCKET)soap->socket, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP setsockopt TCP_NODELAY failed in soap_accept()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#endif +#endif + if (soap->accept_timeout) + { +#if defined(WIN32) + u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)soap->master, FIONBIO, &blocking); + ioctlsocket((SOAP_SOCKET)soap->socket, FIONBIO, &blocking); +/* WR[ */ +#elif defined(VXWORKS) + vx_nonblocking = FALSE; + ioctl((SOAP_SOCKET)soap->master, FIONBIO, (int)(&vx_nonblocking)); + ioctl((SOAP_SOCKET)soap->socket, FIONBIO, (int)(&vx_nonblocking)); +/* ]WR */ +#elif defined(PALM) + fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL,0)&~O_NONBLOCK); + fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL,0)&~O_NONBLOCK); +#elif defined(SYMBIAN) + long blocking = 0; + ioctl((SOAP_SOCKET)soap->master, 0/*FIONBIO*/, &blocking); +#else + fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL)&~O_NONBLOCK); + fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL)&~O_NONBLOCK); +#endif + } + return soap->socket; + } + if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EAGAIN) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept failed from %s\n", soap->host)); + soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "TCP accept failed in soap_accept()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + } + } + else + { soap_set_receiver_error(soap, tcp_error(soap), "TCP no master socket in soap_accept()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_disconnect(struct soap *soap) +{ +#ifdef WITH_OPENSSL + if (soap->ssl) + { int r, s = 0; + if (soap->session) + SSL_SESSION_free(soap->session); + if (*soap->host) + { soap->session = SSL_get1_session(soap->ssl); + if (soap->session) + { strcpy(soap->session_host, soap->host); + soap->session_port = soap->port; + } + } + r = SSL_shutdown(soap->ssl); + if (r != 1) + { s = ERR_get_error(); + if (s) + { if (soap_valid_socket(soap->socket)) + { soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 1); + soap->socket = SOAP_INVALID_SOCKET; + } + r = SSL_shutdown(soap->ssl); + } + } + DBGLOG(TEST, if (s) SOAP_MESSAGE(fdebug, "Shutdown failed: %d\n", SSL_get_error(soap->ssl, r))); + SSL_free(soap->ssl); + soap->ssl = NULL; + if (s) + return SOAP_SSL_ERROR; + ERR_remove_state(0); + } +#endif + if (soap_valid_socket(soap->socket)) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Closing socket %d\n", soap->socket)); + soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 2); + soap->fclosesocket(soap, (SOAP_SOCKET)soap->socket); + soap->socket = SOAP_INVALID_SOCKET; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_closesocket(struct soap *soap, SOAP_SOCKET fd) +{ return closesocket(fd); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_shutdownsocket(struct soap *soap, SOAP_SOCKET fd, int how) +{ return shutdown(fd, how); +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_closesock(struct soap *soap) +{ register int status = soap->error; + if (status == SOAP_EOF || status == SOAP_TCP_ERROR || status == SOAP_SSL_ERROR || !soap->keep_alive) + { if (soap->fclose && (soap->error = soap->fclose(soap))) + return soap->error; + soap->socket = SOAP_INVALID_SOCKET; + soap->keep_alive = 0; + } +#ifdef WITH_ZLIB + if (soap->zlib_state == SOAP_ZLIB_DEFLATE) + deflateEnd(&soap->d_stream); + else if (soap->zlib_state == SOAP_ZLIB_INFLATE) + inflateEnd(&soap->d_stream); + soap->zlib_state = SOAP_ZLIB_NONE; +#endif + return soap->error = status; +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_hash(register const char *s) +{ register size_t h = 0; + while (*s) + h = 65599*h + *s++; + return h % SOAP_IDHASH; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static void +soap_init_pht(struct soap *soap) +{ register int i; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing pointer hashtable\n")); + for (i = 0; i < (int)SOAP_PTRHASH; i++) + soap->pht[i] = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_new1(soap_mode mode) +{ return soap_new2(mode, mode); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_new() +{ return soap_new2(SOAP_IO_DEFAULT, SOAP_IO_DEFAULT); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_new2(soap_mode imode, soap_mode omode) +{ struct soap *soap = (struct soap*)SOAP_MALLOC(sizeof(struct soap)); + if (soap) + soap_init2(soap, imode, omode); + return soap; +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static void +soap_free_pht(struct soap *soap) +{ register struct soap_plist *pp, *next; + register int i; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free pointer hashtable\n")); + for (i = 0; i < (int)SOAP_PTRHASH; i++) + { for (pp = soap->pht[i]; pp; pp = next) + { next = pp->next; + SOAP_FREE(pp); + } + soap->pht[i] = NULL; + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_embed(struct soap *soap, const void *p, const struct soap_array *a, int n, const char *tag, int type) +{ register int i; + struct soap_plist *pp; + if (soap->version != 1) + soap->encoding = 1; + if (a) + i = soap_array_pointer_lookup(soap, p, a, n, type, &pp); + else + i = soap_pointer_lookup(soap, p, type, &pp); + if (i) + { if (soap_is_embedded(soap, pp) + || soap_is_single(soap, pp)) + return 0; + soap_set_embedded(soap, pp); + } + return i; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_pointer_lookup(struct soap *soap, const void *p, int type, struct soap_plist **ppp) +{ register struct soap_plist *pp; + *ppp = NULL; + if (p) + for (pp = soap->pht[soap_hash_ptr(p)]; pp; pp = pp->next) + if (pp->ptr == p && pp->type == type) + { *ppp = pp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d id=%d\n", p, type, pp->id)); + return pp->id; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d: not found\n", p, type)); + return 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_pointer_enter(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp) +{ register int h; + register struct soap_plist *pp = *ppp = (struct soap_plist*)SOAP_MALLOC(sizeof(struct soap_plist)); + if (!pp) + return 0; + if (a) + h = soap_hash_ptr(a->__ptr); + else + h = soap_hash_ptr(p); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pointer enter location=%p array=%p size=%d dim=%d type=%d id=%lu\n", p, a?a->__ptr:NULL, a?a->__size:0, n, type, soap->idnum+1)); + pp->next = soap->pht[h]; + pp->type = type; + pp->mark1 = 0; + pp->mark2 = 0; + pp->ptr = p; + pp->array = a; + soap->pht[h] = pp; + pp->id = ++soap->idnum; + return pp->id; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_array_pointer_lookup(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp) +{ register struct soap_plist *pp; + *ppp = NULL; + if (!p || !a->__ptr) + return 0; + for (pp = soap->pht[soap_hash_ptr(a->__ptr)]; pp; pp = pp->next) + { if (pp->type == type && pp->array && pp->array->__ptr == a->__ptr) + { register int i; + for (i = 0; i < n; i++) + if (((const int*)&pp->array->__size)[i] != ((const int*)&a->__size)[i]) + break; + if (i == n) + { *ppp = pp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d id=%d\n", a->__ptr, type, pp->id)); + return pp->id; + } + } + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d: not found\n", a->__ptr, type)); + return 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_begin_count(struct soap *soap) +{ soap_clr_attr(soap); + soap_set_local_namespaces(soap); +#ifndef WITH_LEANER + if ((soap->mode & SOAP_ENC_DIME) || (soap->omode & SOAP_ENC_DIME)) + soap->mode = soap->omode | SOAP_IO_LENGTH | SOAP_ENC_DIME; + else +#endif + { soap->mode = soap->omode; + if ((soap->mode & SOAP_IO) == SOAP_IO_STORE + || (((soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_ENC_XML)) +#ifndef WITH_LEANER + && !soap->fpreparesend +#endif + )) + soap->mode &= ~SOAP_IO_LENGTH; + else + soap->mode |= SOAP_IO_LENGTH; + } +#ifdef WITH_ZLIB + if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH) + { if (!(soap->mode & SOAP_ENC_DIME)) + soap->mode &= ~SOAP_IO_LENGTH; + if (soap->mode & SOAP_ENC_XML) + soap->mode |= SOAP_IO_BUFFER; + else + soap->mode |= SOAP_IO_STORE; + } + +#endif + if (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH)) + soap->mode |= SOAP_XML_TREE; +#ifndef WITH_LEANER + if (soap->mode & SOAP_ENC_MIME) + soap_select_mime_boundary(soap); + soap->dime.list = soap->dime.last; /* keep track of last DIME attachment */ +#endif + soap->count = 0; + soap->ns = 0; + soap->null = 0; + soap->position = 0; + soap->mustUnderstand = 0; + soap->encoding = 0; + soap->part = SOAP_BEGIN; + soap->idnum = 0; +#ifndef WITH_LEANER + soap->dime.count = 0; /* count # of attachments */ + soap->dime.size = 0; /* accumulate total size of attachments */ + if (soap->fprepareinit && (soap->mode & SOAP_IO) != SOAP_IO_STORE) + soap->fprepareinit(soap); +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin count phase (socket=%d mode=%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count)); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_begin_send(struct soap *soap) +{ soap->error = SOAP_OK; + soap_clr_attr(soap); + soap_set_local_namespaces(soap); + soap->mode = soap->omode | (soap->mode & (SOAP_IO_LENGTH | SOAP_ENC_DIME)); +#ifdef WITH_ZLIB + if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH) + { if (soap->mode & SOAP_ENC_XML) + soap->mode |= SOAP_IO_BUFFER; + else + soap->mode |= SOAP_IO_STORE; + } +#endif + if ((soap->mode & SOAP_IO) == SOAP_IO_FLUSH && soap_valid_socket(soap->socket)) + { if (soap->count || (soap->mode & SOAP_IO_LENGTH) || (soap->mode & SOAP_ENC_XML)) + soap->mode |= SOAP_IO_BUFFER; + else + soap->mode |= SOAP_IO_STORE; + } + soap->mode &= ~SOAP_IO_LENGTH; + if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) + soap_new_block(soap); + if (!(soap->mode & SOAP_IO_KEEPALIVE)) + soap->keep_alive = 0; + if (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH)) + soap->mode |= SOAP_XML_TREE; +#ifndef WITH_LEANER + if (soap->mode & SOAP_ENC_MIME) + soap_select_mime_boundary(soap); +#ifdef WIN32 +#ifndef UNDER_CE +#ifndef WITH_FASTCGI + if (!soap_valid_socket(soap->socket)) /* Set win32 stdout or soap->sendfd to BINARY, e.g. to support DIME */ +#ifdef __BORLANDC__ + setmode((SOAP_SOCKET)soap->sendfd, O_BINARY); +#else + _setmode((SOAP_SOCKET)soap->sendfd, _O_BINARY); +#endif +#endif +#endif +#endif +#endif + if (soap->mode & SOAP_IO) + { soap->bufidx = 0; + soap->buflen = 0; + } + soap->chunksize = 0; + soap->ns = 0; + soap->null = 0; + soap->position = 0; + soap->mustUnderstand = 0; + soap->encoding = 0; + soap->part = SOAP_BEGIN; + soap->idnum = 0; + soap->level = 0; +#ifdef WITH_ZLIB + soap->z_ratio_out = 1.0; + if ((soap->mode & SOAP_ENC_ZLIB) && soap->zlib_state != SOAP_ZLIB_DEFLATE) + { +#ifdef WITH_GZIP + memcpy(soap->z_buf, "\37\213\10\0\0\0\0\0\0\377", 10); + soap->d_stream.next_out = (Byte*)soap->z_buf + 10; + soap->d_stream.avail_out = SOAP_BUFLEN - 10; + soap->z_crc = crc32(0L, NULL, 0); + if (deflateInit2(&soap->d_stream, soap->z_level, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY) != Z_OK) +#else + soap->d_stream.next_out = (Byte*)soap->z_buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + if (deflateInit(&soap->d_stream, soap->z_level) != Z_OK) +#endif + return soap->error = SOAP_ZLIB_ERROR; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflate initialized\n")); + soap->zlib_state = SOAP_ZLIB_DEFLATE; + } +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin send phase (socket=%d mode=%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count)); +#ifndef WITH_LEANER + if (soap->fprepareinit && (soap->mode & SOAP_IO) == SOAP_IO_STORE) + soap->fprepareinit(soap); +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_embedded(struct soap *soap, const void *p, int t) +{ struct soap_plist *pp; + if (soap_pointer_lookup(soap, p, t, &pp)) + { pp->mark1 = 1; + pp->mark2 = 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded %p type=%d mark set to 1\n", p, t)); + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_reference(struct soap *soap, const void *p, int t) +{ + struct soap_plist *pp; + if (!p || (soap->mode & SOAP_XML_TREE)) + return 1; + if (soap_pointer_lookup(soap, p, t, &pp)) + { if (pp->mark1 == 0) + { pp->mark1 = 2; + pp->mark2 = 2; + } + } + else if (soap_pointer_enter(soap, p, NULL, 0, t, &pp)) + { pp->mark1 = 0; + pp->mark2 = 0; + } + else + return 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reference %p type=%d (%d %d)\n", p, t, (int)pp->mark1, (int)pp->mark2)); + return pp->mark1; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_array_reference(struct soap *soap, const void *p, const struct soap_array *a, int n, int t) +{ register int i; + struct soap_plist *pp; + if (!p) + return 1; + i = soap_array_pointer_lookup(soap, p, a, n, t, &pp); + if (i) + { if (pp->mark1 == 0) + { pp->mark1 = 2; + pp->mark2 = 2; + } + } + else if (!soap_pointer_enter(soap, p, a, n, t, &pp)) + return 1; + else + { pp->mark1 = 0; + pp->mark2 = 0; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array reference %p ptr=%p dim=%d type=%d (%d %d)\n", p, a->__ptr, n, t, (int)pp->mark1, (int)pp->mark2)); + return pp->mark1; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_embedded_id(struct soap *soap, int id, const void *p, int t) +{ struct soap_plist *pp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id %p type=%d id=%d\n", p, t, id)); + if (soap->mode & SOAP_XML_TREE) + return id; + if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER) + { if (id < 0) + { id = soap_pointer_lookup(soap, p, t, &pp); + if (id) + { if (soap->mode & SOAP_IO_LENGTH) + pp->mark1 = 2; + else + pp->mark2 = 2; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id multiref id=%d %p type=%d = (%d %d)\n", id, p, t, (int)pp->mark1, (int)pp->mark2)); + } + return -1; + } + return id; + } + if (id < 0) + id = soap_pointer_lookup(soap, p, t, &pp); + else if (id && !soap_pointer_lookup(soap, p, t, &pp)) + return 0; + if (id && pp) + { if (soap->mode & SOAP_IO_LENGTH) + pp->mark1 = 1; + else + pp->mark2 = 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id embedded ref id=%d %p type=%d = (%d %d)\n", id, p, t, (int)pp->mark1, (int)pp->mark2)); + } + return id; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_is_embedded(struct soap *soap, struct soap_plist *pp) +{ if (!pp) + return 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Is embedded? %d %d\n", (int)pp->mark1, (int)pp->mark2)); + if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER) + { if (soap->mode & SOAP_IO_LENGTH) + return pp->mark1 != 0; + return pp->mark2 != 0; + } + if (soap->mode & SOAP_IO_LENGTH) + return pp->mark1 == 1; + return pp->mark2 == 1; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_is_single(struct soap *soap, struct soap_plist *pp) +{ if (soap->part == SOAP_IN_HEADER) + return 1; + if (!pp) + return 0; + if (soap->mode & SOAP_IO_LENGTH) + return pp->mark1 == 0; + return pp->mark2 == 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_embedded(struct soap *soap, struct soap_plist *pp) +{ if (!pp) + return; + if (soap->mode & SOAP_IO_LENGTH) + pp->mark1 = 1; + else + pp->mark2 = 1; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_dime(struct soap *soap, const char *tag, int id, const void *p, const struct soap_array *a, const char *aid, const char *atype, const char *aoptions, int n, const char *type, int t) +{ struct soap_plist *pp; + int i; + if (!p || !a->__ptr || (!aid && !atype)) + return soap_element_id(soap, tag, id, p, a, n, type, t); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attachment tag='%s' id='%s' (%d) type='%s'\n", tag, aid?aid:"", id, atype?atype:"")); + i = soap_array_pointer_lookup(soap, p, a, n, t, &pp); + if (!i) + { i = soap_pointer_enter(soap, p, a, n, t, &pp); + if (!i) + { soap->error = SOAP_EOM; + return -1; + } + } + if (id < 0) + id = i; + if (!aid) + { sprintf(soap->tmpbuf, soap->dime_id_format, id); + aid = soap_strdup(soap, soap->tmpbuf); + } + if (soap_element_href(soap, tag, 0, "href", aid)) + return soap->error; + if (soap->mode & SOAP_IO_LENGTH) + { if (pp->mark1 != 3) + { struct soap_multipart *content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, (char*)a->__ptr, a->__size); + if (!content) + { soap->error = SOAP_EOM; + return -1; + } + content->id = aid; + content->type = atype; + content->options = aoptions; + pp->mark1 = 3; + } + } + else + pp->mark2 = 3; + return -1; +} +#endif +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static void +soap_init_iht(struct soap *soap) +{ register int i; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing ID hashtable\n")); + for (i = 0; i < SOAP_IDHASH; i++) + soap->iht[i] = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static void +soap_free_iht(struct soap *soap) +{ register int i; + register struct soap_ilist *ip, *p; + register struct soap_flist *fp, *fq; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free ID hashtable\n")); + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = p) + { for (fp = ip->flist; fp; fp = fq) + { fq = fp->next; + SOAP_FREE(fp); + } + p = ip->next; + SOAP_FREE(ip); + } + soap->iht[i] = NULL; + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +static struct soap_ilist * +soap_hlookup(struct soap *soap, const char *id) +{ register struct soap_ilist *ip; + for (ip = soap->iht[soap_hash(id)]; ip; ip = ip->next) + if (!strcmp(ip->id, id)) + return ip; + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +struct soap_ilist * +SOAP_FMAC2 +soap_lookup(struct soap *soap, const char *id) +{ register struct soap_ilist *ip; + ip = soap_hlookup(soap, id); +#ifndef WITH_LEANER + if (!ip && *id != '#' && !strchr(id, ':')) /* try content id "cid:" with DIME attachments */ + { char cid[SOAP_TAGLEN]; + strcpy(cid, "cid:"); + strncat(cid + 4, id, sizeof(cid) - 5); + cid[sizeof(cid) - 1] = '\0'; + ip = soap_hlookup(soap, cid); + } +#endif + return ip; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +struct soap_ilist * +SOAP_FMAC2 +soap_enter(struct soap *soap, const char *id) +{ register size_t h; + register struct soap_ilist *ip; + ip = (struct soap_ilist*)SOAP_MALLOC(sizeof(struct soap_ilist) + strlen(id)); + if (ip) + { h = soap_hash(id); + strcpy(ip->id, id); + ip->next = soap->iht[h]; + soap->iht[h] = ip; + return ip; + } + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_malloc(struct soap *soap, size_t n) +{ register char *p; + if (!n) + return NULL; + if (!soap) + return SOAP_MALLOC(n); + n += (-(long)n) & 7; + if (!(p = (char*)SOAP_MALLOC(n + sizeof(void*) + sizeof(size_t)))) + { soap->error = SOAP_EOM; + return NULL; + } + /* keep chain of alloced cells for later destruction */ + soap->alloced = 1; + *(void**)(p + n) = soap->alist; + *(size_t*)(p + n + sizeof(void*)) = n; + soap->alist = p + n; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Malloc %u bytes at location %p\n", (unsigned int)n, p)); + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_dealloc(struct soap *soap, void *p) +{ if (!soap) + return; + if (p) + { register char **q; + for (q = (char**)&soap->alist; *q; q = *(char***)q) + { if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*)))) + { *q = **(char***)q; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Freed data at %p\n", p)); + SOAP_FREE(p); + return; + } + } + soap_delete(soap, p); + } + else + { register char *q; + while (soap->alist) + { q = (char*)soap->alist; + soap->alist = *(void**)q; + q -= *(size_t*)(q + sizeof(void*)); + SOAP_FREE(q); + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Dealloc all data done\n")); + } + /* we must assume these were deallocated: */ + soap->action = NULL; + soap->fault = NULL; + soap->header = NULL; + soap->authrealm = NULL; +#ifndef WITH_LEANER + soap_clr_mime(soap); +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_delete(struct soap *soap, void *p) +{ register struct soap_clist **cp = &soap->clist; + if (p) + { while (*cp) + { if (p == (*cp)->ptr) + { register struct soap_clist *q = *cp; + *cp = q->next; + q->fdelete(q); + SOAP_FREE(q); + return; + } + cp = &(*cp)->next; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: address not in list\n", p)); + } + else + { while (*cp) + { register struct soap_clist *q = *cp; + *cp = q->next; + if (q->ptr == (void*)soap->fault) + soap->fault = NULL; /* this was deallocated */ + else if (q->ptr == (void*)soap->header) + soap->header = NULL; /* this was deallocated */ + q->fdelete(q); + SOAP_FREE(q); + } + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +struct soap_clist * +SOAP_FMAC2 +soap_link(struct soap *soap, void *p, int t, int n, void (*fdelete)(struct soap_clist*)) +{ register struct soap_clist *cp; + if ((cp = (struct soap_clist*)SOAP_MALLOC(sizeof(struct soap_clist)))) + { cp->next = soap->clist; + cp->type = t; + cp->size = n; + cp->ptr = p; + cp->fdelete = fdelete; + soap->clist = cp; + } + return cp; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_unlink(struct soap *soap, const void *p) +{ register char **q; + register struct soap_clist **cp; + if (!soap || !p) + return; + for (q = (char**)&soap->alist; *q; q = *(char***)q) + { if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*)))) + { *q = **(char***)q; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked data %p\n", p)); + return; + } + } + for (cp = &soap->clist; *cp; cp = &(*cp)->next) + { if (p == (*cp)->ptr) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked class instance %p\n", p)); + q = (char**)*cp; + *cp = (*cp)->next; + SOAP_FREE(q); + return; + } + } +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_lookup_type(struct soap *soap, const char *id) +{ register struct soap_ilist *ip; + if (id && *id) + { ip = soap_lookup(soap, id); + if (ip) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup id='%s' type=%d\n", id, ip->type)); + return ip->type; + } + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "lookup type id='%s' NOT FOUND! Need to get it from xsi:type\n", id)); + return 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_id_lookup(struct soap *soap, const char *id, void **p, int t, size_t n, unsigned int k) +{ struct soap_ilist *ip; + void **q; + if (!p || !id || !*id) + return p; + ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */ + if (!ip) + { ip = soap_enter(soap, id); /* new hash table entry for string id */ + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding first href='%s' type=%d %p (%u bytes)\n", id, t, p, (unsigned int)n)); + ip->type = t; + ip->size = n; + ip->link = p; + ip->copy = NULL; + ip->flist = NULL; + ip->ptr = NULL; + ip->level = k; + *p = NULL; + } + else if (ip->ptr) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolved href='%s' type=%d location=%p (%u bytes)\n", id, t, ip->ptr, (unsigned int)n)); + if (ip->type != t) + { strcpy(soap->id, id); + soap->error = SOAP_HREF; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility: id type=%d href type=%d\n", ip->type, t)); + return NULL; + } + while (ip->level < k) + { q = (void**)soap_malloc(soap, sizeof(void*)); + if (!q) + return NULL; + *p = (void*)q; + p = q; + k--; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); + } + *p = ip->ptr; + } + else if (ip->level > k) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving level %u pointers to href='%s'\n", ip->level, id)); + while (ip->level > k) + { void *s, **r = &ip->link; + q = (void**)ip->link; + while (q) + { *r = (void*)soap_malloc(soap, sizeof(void*)); + s = *q; + *q = *r; + r = (void**)*r; + q = (void**)s; + } + *r = NULL; + ip->size = n; + ip->copy = NULL; + ip->level = ip->level - 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); + } + q = (void**)ip->link; + ip->link = p; + *p = (void*)q; + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarded href='%s' type=%d location=%p (%u bytes)\n", id, t, p, (unsigned int)n)); + while (ip->level < k) + { q = (void**)soap_malloc(soap, sizeof(void*)); + *p = q; + p = q; + k--; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); + } + q = (void**)ip->link; + ip->link = p; + *p = (void*)q; + } + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_id_forward(struct soap *soap, const char *href, void *p, int st, int tt, size_t n, unsigned int k, void (*fcopy)(struct soap*, int, int, void*, const void*, size_t)) +{ struct soap_ilist *ip; + if (!p || !href || !*href) + return p; + ip = soap_lookup(soap, href); /* lookup pointer to hash table entry for string id */ + if (!ip) + { ip = soap_enter(soap, href); /* new hash table entry for string id */ + ip->type = st; + ip->size = n; + ip->link = NULL; + ip->copy = NULL; + ip->ptr = NULL; + ip->level = 0; + ip->flist = NULL; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "New entry href='%s' type=%d size=%lu level=%d location=%p\n", href, st, (unsigned long)n, k, p)); + } + else if (ip->type != st || (ip->level == k && ip->size != n)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n", href, ip->type, (unsigned long)ip->size, k, st, (unsigned long)n)); + strcpy(soap->id, href); + soap->error = SOAP_HREF; + return NULL; + } + if (fcopy || n < sizeof(void*) || *href != '#') + { register struct soap_flist *fp = (struct soap_flist*)SOAP_MALLOC(sizeof(struct soap_flist)); + if (!fp) + { soap->error = SOAP_EOM; + return NULL; + } + fp->next = ip->flist; + fp->type = tt; + fp->ptr = p; + fp->level = k; + if (fcopy) + fp->fcopy = fcopy; + else + fp->fcopy = soap_fcopy; + ip->flist = fp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding type=%d (target type=%d) size=%lu location=%p level=%u href='%s'\n", st, tt, (unsigned long)n, p, k, href)); + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding copying address %p for type=%d href='%s'\n", p, st, href)); + *(void**)p = ip->copy; + ip->copy = p; + } + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_id_enter(struct soap *soap, const char *id, void *p, int t, size_t n, unsigned int k, const char *type, const char *arrayType, void *(*finstantiate)(struct soap*, int, const char*, const char*, size_t*)) +{ struct soap_ilist *ip; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Enter id='%s' type=%d loc=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k)); + soap->alloced = 0; + if (!p) + { if (finstantiate) + p = finstantiate(soap, t, type, arrayType, &n); + else + p = soap_malloc(soap, n); + if (p) + soap->alloced = 1; + } +#ifndef WITH_NOIDREF + if (!id || !*id) +#endif + return p; +#ifndef WITH_NOIDREF + ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */ + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Lookup entry id='%s for location=%p'\n", id, p)); + if (!ip) + { ip = soap_enter(soap, id); /* new hash table entry for string id */ + ip->type = t; + ip->link = NULL; + ip->copy = NULL; + ip->flist = NULL; + ip->size = n; + ip->ptr = p; + ip->level = k; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "New entry id='%s' type=%d size=%lu level=%u location=%p\n", id, t, (unsigned long)n, k, p)); + } + else if ((ip->type != t || (ip->level == k && ip->size != n)) && (ip->copy || ip->flist)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n", id, ip->type, (unsigned long)ip->size, k, t, (unsigned long)n)); + strcpy(soap->id, id); + soap->error = SOAP_HREF; + return NULL; + } + else if (ip->ptr) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Multiply defined id='%s'\n", id)); + strcpy(soap->id, id); + soap->error = SOAP_MULTI_ID; + return NULL; + } + else + { ip->size = n; + ip->ptr = p; + ip->level = k; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update entry id='%s' type=%d location=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k)); + } + return ip->ptr; +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_fcopy(struct soap *soap, int st, int tt, void *p, const void *q, size_t n) +{ DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Copying data type=%d (target type=%d) %p -> %p (%lu bytes)\n", st, tt, q, p, (unsigned long)n)); + memcpy(p, q, n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_end_send(struct soap *soap) +{ +#ifndef WITH_LEANER + if (soap->dime.list) + { /* SOAP body referenced attachments must appear first */ + soap->dime.last->next = soap->dime.first; + soap->dime.first = soap->dime.list->next; + soap->dime.list->next = NULL; + soap->dime.last = soap->dime.list; + } + if (soap_putdime(soap) || soap_putmime(soap)) + return soap->error; + soap->mime.list = NULL; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->dime.list = NULL; + soap->dime.first = NULL; + soap->dime.last = NULL; +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End send\n")); + if (soap->mode & SOAP_IO) /* need to flush the remaining data in buffer */ + { if (soap_flush(soap)) +#ifdef WITH_ZLIB + { if (soap->mode & SOAP_ENC_ZLIB && soap->zlib_state == SOAP_ZLIB_DEFLATE) + { soap->zlib_state = SOAP_ZLIB_NONE; + deflateEnd(&soap->d_stream); + } + return soap->error; + } +#else + return soap->error; +#endif +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { int r; + soap->d_stream.avail_in = 0; + do + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating remainder\n")); + r = deflate(&soap->d_stream, Z_FINISH); + if (soap->d_stream.avail_out != SOAP_BUFLEN) + { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN - soap->d_stream.avail_out)) + { soap->zlib_state = SOAP_ZLIB_NONE; + deflateEnd(&soap->d_stream); + return soap->error; + } + soap->d_stream.next_out = (Byte*)soap->z_buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + } + } while (r == Z_OK); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out)); + soap->z_ratio_out = (float)soap->d_stream.total_out / (float)soap->d_stream.total_in; + soap->mode &= ~SOAP_ENC_ZLIB; + soap->zlib_state = SOAP_ZLIB_NONE; + if (deflateEnd(&soap->d_stream) != Z_OK || r != Z_STREAM_END) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to end deflate: %s\n", soap->d_stream.msg?soap->d_stream.msg:"")); + return soap->error = SOAP_ZLIB_ERROR; + } +#ifdef WITH_GZIP + soap->z_buf[0] = soap->z_crc & 0xFF; + soap->z_buf[1] = (soap->z_crc >> 8) & 0xFF; + soap->z_buf[2] = (soap->z_crc >> 16) & 0xFF; + soap->z_buf[3] = (soap->z_crc >> 24) & 0xFF; + soap->z_buf[4] = soap->d_stream.total_in & 0xFF; + soap->z_buf[5] = (soap->d_stream.total_in >> 8) & 0xFF; + soap->z_buf[6] = (soap->d_stream.total_in >> 16) & 0xFF; + soap->z_buf[7] = (soap->d_stream.total_in >> 24) & 0xFF; + if (soap_flush_raw(soap, soap->z_buf, 8)) + return soap->error; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip crc32=%lu\n", (unsigned long)soap->z_crc)); +#endif + } +#endif + if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) + { char *p; +#ifndef WITH_NOHTTP + if (!(soap->mode & SOAP_ENC_XML)) + { soap->mode--; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending buffered message of length %u\n", (unsigned int)soap->blist->size)); + if (soap->status >= SOAP_POST) + soap->error = soap->fpost(soap, soap->endpoint, soap->host, soap->port, soap->path, soap->action, soap->blist->size); + else if (soap->status != SOAP_STOP) + soap->error = soap->fresponse(soap, soap->status, soap->blist->size); + if (soap->error || soap_flush(soap)) + return soap->error; + soap->mode++; + } +#endif + for (p = soap_first_block(soap); p; p = soap_next_block(soap)) + { DBGMSG(SENT, p, soap_block_size(soap)); + if ((soap->error = soap->fsend(soap, p, soap_block_size(soap)))) + { soap_end_block(soap); + return soap->error; + } + } + soap_end_block(soap); + } +#ifndef WITH_LEANER + else if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) + { DBGMSG(SENT, "\r\n0\r\n\r\n", 7); + if ((soap->error = soap->fsend(soap, "\r\n0\r\n\r\n", 7))) + return soap->error; + } +#endif + } +#ifdef WITH_OPENSSL + if (!soap->ssl && soap_valid_socket(soap->socket) && !soap->keep_alive) + soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 1); /* Send TCP FIN */ +#else + if (soap_valid_socket(soap->socket) && !soap->keep_alive) + soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 1); /* Send TCP FIN */ +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of send message ok\n")); + soap->part = SOAP_END; + soap->count = 0; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_end_recv(struct soap *soap) +{ soap->part = SOAP_END; +#ifndef WITH_LEANER + if ((soap->mode & SOAP_ENC_MIME) && soap_getmime(soap)) + return soap->error; + soap->mime.list = soap->mime.first; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->dime.list = soap->dime.first; + soap->dime.first = NULL; + soap->dime.last = NULL; +#endif + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "End of receive message ok\n")); +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { soap->mode &= ~SOAP_ENC_ZLIB; + memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN); + soap->bufidx = (char*)soap->d_stream.next_in - soap->z_buf; + soap->buflen = soap->z_buflen; + soap->zlib_state = SOAP_ZLIB_NONE; + if (inflateEnd(&soap->d_stream) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; +#ifdef WITH_GZIP + if (soap->zlib_in == SOAP_ZLIB_GZIP) + { soap_wchar c; + short i; + for (i = 0; i < 8; i++) + { if ((int)(c = soap_getchar(soap)) == EOF) + return soap->error = SOAP_EOF; + soap->z_buf[i] = (char)c; + } + if (soap->z_crc != ((uLong)(unsigned char)soap->z_buf[0] | ((uLong)(unsigned char)soap->z_buf[1] << 8) | ((uLong)(unsigned char)soap->z_buf[2] << 16) | ((uLong)(unsigned char)soap->z_buf[3] << 24))) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: crc check failed, message corrupted? (crc32=%lu)\n", (unsigned long)soap->z_crc)); + return soap->error = SOAP_ZLIB_ERROR; + } + if (soap->d_stream.total_out != ((uLong)(unsigned char)soap->z_buf[4] | ((uLong)(unsigned char)soap->z_buf[5] << 8) | ((uLong)(unsigned char)soap->z_buf[6] << 16) | ((uLong)(unsigned char)soap->z_buf[7] << 24))) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: incorrect message length\n")); + return soap->error = SOAP_ZLIB_ERROR; + } + } +#endif + } +#endif + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) + while ((int)soap_getchar(soap) != EOF) /* advance to last chunk */ + ; + if (soap->fdisconnect && (soap->error = soap->fdisconnect(soap))) + return soap->error; +#ifndef WITH_NOIDREF + return soap_resolve(soap); +#else + return SOAP_OK; +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_free(struct soap *soap) +{ register struct soap_nlist *np; + register struct soap_attribute *tp; + register struct Namespace *ns; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free namespace stack\n")); + while (soap->nlist) + { np = soap->nlist->next; + if (soap->nlist->ns) + SOAP_FREE(soap->nlist->ns); + SOAP_FREE(soap->nlist); + soap->nlist = np; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free any remaining temp blocks\n")); + while (soap->blist) + soap_end_block(soap); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attributes\n")); + while (soap->attributes) + { tp = soap->attributes->next; + if (soap->attributes->value) + SOAP_FREE(soap->attributes->value); + SOAP_FREE(soap->attributes); + soap->attributes = tp; + } +#ifdef WITH_FAST + if (soap->labbuf) + SOAP_FREE(soap->labbuf); + soap->labbuf = NULL; + soap->lablen = 0; + soap->labidx = 0; +#endif +#ifndef WITH_NOIDREF + soap_free_pht(soap); + soap_free_iht(soap); +#endif + ns = soap->local_namespaces; + if (ns) + { for (; ns->id; ns++) + { if (ns->out) + { SOAP_FREE(ns->out); + if (soap->encodingStyle == ns->out) + soap->encodingStyle = SOAP_STR_EOS; + ns->out = NULL; + } + if (soap->encodingStyle == ns->ns) + soap->encodingStyle = SOAP_STR_EOS; + } + SOAP_FREE(soap->local_namespaces); + soap->local_namespaces = NULL; + } +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +static void +soap_init_logs(struct soap *soap) +{ int i; + for (i = 0; i < SOAP_MAXLOGS; i++) + { soap->logfile[i] = NULL; + soap->fdebug[i] = NULL; + } +} +#endif + +/******************************************************************************/ +#if !defined(WITH_LEAN) || defined(SOAP_DEBUG) +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_open_logfile(struct soap *soap, int i) +{ if (soap->logfile[i]) + soap->fdebug[i] = fopen(soap->logfile[i], i < 2 ? "ab" : "a"); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +static void +soap_close_logfile(struct soap *soap, int i) +{ if (soap->fdebug[i]) + { fclose(soap->fdebug[i]); + soap->fdebug[i] = NULL; + } +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_close_logfiles(struct soap *soap) +{ int i; + for (i = 0; i < SOAP_MAXLOGS; i++) + soap_close_logfile(soap, i); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +static void +soap_set_logfile(struct soap *soap, int i, const char *logfile) +{ char *s = NULL; + soap_close_logfile(soap, i); + if (soap->logfile[i]) + SOAP_FREE((void*)soap->logfile[i]); + if (logfile) + if ((s = (char*)SOAP_MALLOC(strlen(logfile) + 1))) + strcpy(s, logfile); + soap->logfile[i] = s; +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_recv_logfile(struct soap *soap, const char *logfile) +{ soap_set_logfile(soap, SOAP_INDEX_RECV, logfile); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_sent_logfile(struct soap *soap, const char *logfile) +{ soap_set_logfile(soap, SOAP_INDEX_SENT, logfile); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_test_logfile(struct soap *soap, const char *logfile) +{ soap_set_logfile(soap, SOAP_INDEX_TEST, logfile); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_copy(struct soap *soap) +{ return soap_copy_context((struct soap*)SOAP_MALLOC(sizeof(struct soap)), soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_copy_context(struct soap *copy, struct soap *soap) +{ if (copy) + { register struct soap_plugin *p; + memcpy(copy, soap, sizeof(struct soap)); + copy->copy = 1; + copy->user = NULL; + copy->userid = NULL; + copy->passwd = NULL; + copy->nlist = NULL; + copy->blist = NULL; + copy->clist = NULL; + copy->alist = NULL; + copy->attributes = NULL; + copy->local_namespaces = NULL; + soap_set_local_namespaces(copy); +#ifndef WITH_NOIDREF + soap_init_iht(copy); + soap_init_pht(copy); +#endif + copy->header = NULL; + copy->fault = NULL; + copy->action = NULL; + *copy->host = '\0'; +#ifndef WITH_LEAN +#ifdef WITH_COOKIES + copy->cookies = soap_copy_cookies(soap); +#else + copy->cookies = NULL; +#endif +#endif +#ifdef SOAP_DEBUG + soap_init_logs(copy); + soap_set_recv_logfile(copy, "RECV.log"); + soap_set_sent_logfile(copy, "SENT.log"); + soap_set_test_logfile(copy, "TEST.log"); +#endif + copy->plugins = NULL; + for (p = soap->plugins; p; p = p->next) + { register struct soap_plugin *q = (struct soap_plugin*)SOAP_MALLOC(sizeof(struct soap_plugin)); + if (!q) + return NULL; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying plugin '%s'\n", p->id)); + *q = *p; + if (p->fcopy && (soap->error = p->fcopy(soap, q, p))) + { SOAP_FREE(q); + return NULL; + } + q->next = copy->plugins; + copy->plugins = q; + } + } + else + soap->error = SOAP_EOM; + return copy; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_init(struct soap *soap) +{ soap->version = 0; + soap_imode(soap, SOAP_IO_DEFAULT); + soap_omode(soap, SOAP_IO_DEFAULT); + soap->copy = 0; + soap->plugins = NULL; + soap->user = NULL; + soap->userid = NULL; + soap->passwd = NULL; +#ifndef WITH_NOHTTP + soap->fpost = http_post; + soap->fget = http_get; + soap->fposthdr = http_post_header; + soap->fresponse = http_response; + soap->fparse = http_parse; + soap->fparsehdr = http_parse_header; +#endif + soap->fconnect = NULL; + soap->fdisconnect = NULL; +#ifndef WITH_NOIO +#ifndef WITH_IPV6 + soap->fresolve = tcp_gethost; +#else + soap->fresolve = NULL; +#endif + soap->faccept = tcp_accept; + soap->fopen = tcp_connect; + soap->fclose = tcp_disconnect; + soap->fclosesocket = tcp_closesocket; + soap->fshutdownsocket = tcp_shutdownsocket; + soap->fsend = fsend; + soap->frecv = frecv; + soap->fpoll = soap_poll; +#else + soap->fopen = NULL; + soap->fclose = NULL; + soap->fpoll = NULL; +#endif +#ifndef WITH_LEANER + soap->fprepareinit = NULL; + soap->fpreparesend = NULL; + soap->fpreparerecv = NULL; +#endif + soap->fignore = NULL; + soap->fserveloop = NULL; + soap->fplugin = fplugin; +#ifndef WITH_LEANER + soap->fdimereadopen = NULL; + soap->fdimewriteopen = NULL; + soap->fdimereadclose = NULL; + soap->fdimewriteclose = NULL; + soap->fdimeread = NULL; + soap->fdimewrite = NULL; +#endif + soap->float_format = "%.8g"; /* .8 preserves single FP precision as much as possible, but might not be very efficient */ + soap->double_format = "%.17lg"; /* .17 preserves double FP precision as much as possible, but might not be very efficient */ + soap->dime_id_format = "cid:id%d"; /* default DIME id format */ + soap->http_version = "1.1"; + soap->actor = NULL; + soap->max_keep_alive = SOAP_MAXKEEPALIVE; + soap->keep_alive = 0; + soap->recv_timeout = 0; + soap->send_timeout = 0; + soap->connect_timeout = 0; + soap->accept_timeout = 0; + soap->socket_flags = 0; + soap->connect_flags = 0; + soap->bind_flags = 0; + soap->accept_flags = 0; + soap->ip = 0; +#ifdef WITH_FAST + soap->labbuf = NULL; + soap->lablen = 0; + soap->labidx = 0; +#endif + soap->encodingStyle = SOAP_STR_EOS; +#ifndef WITH_NONAMESPACES + soap->namespaces = namespaces; +#else + soap->namespaces = NULL; +#endif + soap->local_namespaces = NULL; + soap->nlist = NULL; + soap->blist = NULL; + soap->clist = NULL; + soap->alist = NULL; + soap->attributes = NULL; + soap->header = NULL; + soap->fault = NULL; + soap->master = SOAP_INVALID_SOCKET; + soap->socket = SOAP_INVALID_SOCKET; + soap->os = NULL; + soap->is = NULL; +#ifndef WITH_LEANER + soap->dom = NULL; + soap->dime.list = NULL; + soap->dime.first = NULL; + soap->dime.last = NULL; + soap->mime.list = NULL; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = NULL; + soap->mime.start = NULL; +#endif +#ifndef UNDER_CE + soap->recvfd = 0; + soap->sendfd = 1; +#else + soap->recvfd = stdin; + soap->sendfd = stdout; +#endif + soap->host[0] = '\0'; + soap->port = 0; + soap->action = NULL; + soap->proxy_host = NULL; + soap->proxy_port = 8080; + soap->proxy_userid = NULL; + soap->proxy_passwd = NULL; + soap->authrealm = NULL; + soap->prolog = NULL; +#ifdef WITH_OPENSSL + soap->fsslauth = ssl_auth_init; + soap->fsslverify = ssl_verify_callback; + soap->bio = NULL; + soap->ssl = NULL; + soap->ctx = NULL; + soap->require_server_auth = 0; + soap->require_client_auth = 0; + soap->rsa = 0; + soap->keyfile = NULL; + soap->password = NULL; + soap->dhfile = NULL; + soap->cafile = NULL; + soap->capath = NULL; + soap->randfile = NULL; + soap->session = NULL; +#endif +#ifdef WITH_ZLIB + soap->zlib_state = SOAP_ZLIB_NONE; + soap->zlib_in = SOAP_ZLIB_NONE; + soap->zlib_out = SOAP_ZLIB_NONE; + soap->d_stream.zalloc = NULL; + soap->d_stream.zfree = NULL; + soap->d_stream.opaque = NULL; + soap->z_level = 6; +#endif +#ifndef WITH_LEAN + soap->cookies = NULL; + soap->cookie_domain = NULL; + soap->cookie_path = NULL; + soap->cookie_max = 32; +#endif +#ifdef SOAP_DEBUG + soap_init_logs(soap); + soap_set_recv_logfile(soap, "RECV.log"); + soap_set_sent_logfile(soap, "SENT.log"); + soap_set_test_logfile(soap, NULL); +#endif +/* WR[ */ +#ifdef WMW_RPM_IO + soap->rpmreqid = NULL; +#endif /* WMW_RPM_IO */ +/* ]WR */ +#ifdef PALM + palmNetLibOpen(); +#endif +#ifndef WITH_NOIDREF + soap_init_iht(soap); + soap_init_pht(soap); +#endif + soap_begin(soap); +#ifdef SOAP_DEBUG + soap_set_test_logfile(soap, "TEST.log"); +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_init1(struct soap *soap, soap_mode mode) +{ soap_init2(soap, mode, mode); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_init2(struct soap *soap, soap_mode imode, soap_mode omode) +{ soap_init(soap); + soap_imode(soap, imode); + soap_omode(soap, omode); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_begin(struct soap *soap) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing\n")); + if (!soap->keep_alive) + { soap->buflen = 0; + soap->bufidx = 0; + } + soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0); + soap->null = 0; + soap->position = 0; + soap->encoding = 0; + soap->mustUnderstand = 0; + soap->mode = 0; + soap->ns = 0; + soap->part = SOAP_BEGIN; + soap->alloced = 0; + soap->count = 0; + soap->length = 0; + soap->cdata = 0; + soap->error = SOAP_OK; + soap->peeked = 0; + soap->ahead = 0; + soap->idnum = 0; + soap->level = 0; + soap->endpoint[0] = '\0'; +#ifndef WITH_LEANER + soap->dime.chunksize = 0; + soap->dime.buflen = 0; +#endif + soap_free(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_end(struct soap *soap) +{ register struct soap_clist *cp; + soap_free(soap); + soap_dealloc(soap, NULL); + while (soap->clist) + { cp = soap->clist->next; + SOAP_FREE(soap->clist); + soap->clist = cp; + } + soap_closesock(soap); +#ifdef SOAP_DEBUG + soap_close_logfiles(soap); +#endif +#ifdef PALM + palmNetLibClose(); +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_namespaces(struct soap *soap, struct Namespace *p) +{ struct Namespace *ns = soap->local_namespaces; + struct soap_nlist *np, *nq, *nr; + unsigned int level = soap->level; + soap->namespaces = p; + soap->local_namespaces = NULL; + soap_set_local_namespaces(soap); + /* reverse the list */ + np = soap->nlist; + soap->nlist = NULL; + if (np) + { nq = np->next; + np->next = NULL; + while (nq) + { nr = nq->next; + nq->next = np; + np = nq; + nq = nr; + } + } + while (np) + { soap->level = np->level; /* preserve element nesting level */ + if (np->ns) + { if (soap_push_namespace(soap, np->id, np->ns)) + return soap->error; + } + else if (np->index >= 0 && ns) + { if (ns[np->index].out) + { if (soap_push_namespace(soap, np->id, ns[np->index].out)) + return soap->error; + } + else if (soap_push_namespace(soap, np->id, ns[np->index].ns)) + return soap->error; + } + if (np->ns) + SOAP_FREE(np->ns); + nq = np; + np = np->next; + SOAP_FREE(nq); + } + if (ns) + { int i; + for (i = 0; ns[i].id; i++) + { if (ns[i].out) + { SOAP_FREE(ns[i].out); + ns[i].out = NULL; + } + } + SOAP_FREE(ns); + } + soap->level = level; /* restore level */ + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static void +soap_set_local_namespaces(struct soap *soap) +{ if (soap->namespaces && !soap->local_namespaces) + { register const struct Namespace *ns1; + register struct Namespace *ns2; + register size_t n = 1; + for (ns1 = soap->namespaces; ns1->id; ns1++) + n++; + n *= sizeof(struct Namespace); + ns2 = (struct Namespace*)SOAP_MALLOC(n); + if (ns2) + { memcpy(ns2, soap->namespaces, n); + if (ns2[0].ns) + { if (!strcmp(ns2[0].ns, soap_env1)) + soap->version = 1; + else + soap->version = 2; + } + soap->local_namespaces = ns2; + } + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element(struct soap *soap, const char *tag, int id, const char *type) +{ struct Namespace *ns = soap->local_namespaces; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element begin tag='%s' id='%d' type='%s'\n", tag, id, type?type:"")); +/**/ +#ifdef WITH_DOM + if (soap->mode & SOAP_XML_DOM) + { register struct soap_dom_element *p, *e = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element)); + e->next = NULL; + e->prnt = soap->dom; + e->nstr = NULL; + e->name = soap_strdup(soap, tag); /* check EOM? */ + e->data = NULL; + e->type = 0; + e->node = NULL; + e->elts = NULL; + e->atts = NULL; + if (soap->dom) + { p = soap->dom->elts; + if (p) + { while (p->next) + p = p->next; + p->next = e; + } + else + soap->dom->elts = e; + } + soap->dom = e; + } + else +#endif +{ + soap->level++; + if (!soap->ns && !(soap->mode & SOAP_XML_CANONICAL)) + if (soap_send(soap, soap->prolog ? soap->prolog : "")) + return soap->error; + if (soap_send_raw(soap, "<", 1) + || soap_send(soap, tag)) + return soap->error; +} +/**/ + if (!soap->ns) + { for (ns = soap->local_namespaces; ns && ns->id; ns++) + { if (*ns->id && (ns->out || ns->ns)) + { sprintf(soap->tmpbuf, "xmlns:%s", ns->id); + if (soap_attribute(soap, soap->tmpbuf, ns->out ? ns->out : ns->ns)) + return soap->error; + } + } + soap->ns = 1; + } + if (id > 0) + { sprintf(soap->tmpbuf, "_%d", id); + if (soap_attribute(soap, "id", soap->tmpbuf)) + return soap->error; + } + if (type && *type) + { if (soap_attribute(soap, "xsi:type", type)) + return soap->error; + } + if (soap->null && soap->position > 0) + { int i; + sprintf(soap->tmpbuf, "[%d", soap->positions[0]); + for (i = 1; i < soap->position; i++) + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), ",%d", soap->positions[i]); + strcat(soap->tmpbuf, "]"); + if (soap_attribute(soap, "SOAP-ENC:position", soap->tmpbuf)) + return soap->error; + } + if (soap->mustUnderstand) + { if (soap->actor && *soap->actor) + { if (soap_attribute(soap, soap->version == 2 ? "SOAP-ENV:role" : "SOAP-ENV:actor", soap->actor)) + return soap->error; + } + if (soap_attribute(soap, "SOAP-ENV:mustUnderstand", soap->version == 2 ? "true" : "1")) + return soap->error; + soap->mustUnderstand = 0; + } + if (soap->encoding) + { if (soap->encodingStyle && soap->local_namespaces) + { if (!*soap->encodingStyle) + { if (soap->local_namespaces[1].out) + soap->encodingStyle = soap->local_namespaces[1].out; + else + soap->encodingStyle = soap->local_namespaces[1].ns; + } + if (soap_attribute(soap, "SOAP-ENV:encodingStyle", soap->encodingStyle)) + return soap->error; + } + soap->encoding = 0; + } + soap->null = 0; + soap->position = 0; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_begin_out(struct soap *soap, const char *tag, int id, const char *type) +{ if (*tag == '-') + return SOAP_OK; + if (soap_element(soap, tag, id, type)) + return soap->error; + return soap_element_start_end_out(soap, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +#ifndef HAVE_STRRCHR +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_strrchr(const char *s, int t) +{ register char *r = NULL; + while (*s) + if (*s++ == t) + r = (char*)s - 1; + return r; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +#ifndef HAVE_STRTOL +SOAP_FMAC1 +long +SOAP_FMAC2 +soap_strtol(const char *s, char **t, int b) +{ register long n = 0; + register int c; + while (*s > 0 && *s <= 32) + s++; + if (b == 10) + { short neg = 0; + if (*s == '-') + { s++; + neg = 1; + } + else if (*s == '+') + s++; + while ((c = *s) && c >= '0' && c <= '9') + { if (n > 214748364) + break; + n *= 10; + n += c - '0'; + s++; + } + if (neg) + n = -n; + } + else /* b == 16 and value is always positive */ + { while ((c = *s)) + { if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'F') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'f') + c -= 'a' - 10; + if (n > 0x07FFFFFF) + break; + n <<= 4; + n += c; + s++; + } + } + if (t) + *t = (char*)s; + return n; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +#ifndef HAVE_STRTOUL +SOAP_FMAC1 +unsigned long +SOAP_FMAC2 +soap_strtoul(const char *s, char **t, int b) +{ unsigned long n = 0; + register int c; + while (*s > 0 && *s <= 32) + s++; + if (b == 10) + { if (*s == '+') + s++; + while ((c = *s) && c >= '0' && c <= '9') + { if (n > 429496729) + break; + n *= 10; + n += c - '0'; + s++; + } + } + else /* b == 16 */ + { while ((c = *s)) + { if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'F') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'f') + c -= 'a' - 10; + if (n > 0x0FFFFFFF) + break; + n <<= 4; + n += c; + s++; + } + } + if (t) + *t = (char*)s; + return n; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_array_begin_out(struct soap *soap, const char *tag, int id, const char *type, const char *offset) +{ if (soap_element(soap, tag, id, "SOAP-ENC:Array")) + return soap->error; + if (soap->version == 2) + { const char *s; + s = soap_strrchr(type, '['); + if ((size_t)(s - type) < sizeof(soap->tmpbuf)) + { strncpy(soap->tmpbuf, type, s - type); + soap->tmpbuf[s - type] = '\0'; + if (type && *type && (soap_attribute(soap, "SOAP-ENC:itemType", soap->tmpbuf))) + return soap->error; + if (s && (soap_attribute(soap, "SOAP-ENC:arraySize", s + 1))) + return soap->error; + } + } + else + { if (offset && (soap_attribute(soap, "SOAP-ENC:offset", offset))) + return soap->error; + if (type && *type && (soap_attribute(soap, "SOAP-ENC:arrayType", type))) + return soap->error; + } + return soap_element_start_end_out(soap, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_start_end_out(struct soap *soap, const char *tag) +{ register struct soap_attribute *tp; +/**/ +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible) + { register struct soap_dom_attribute *a = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); + a->next = soap->dom->atts; + a->nstr = NULL; + a->name = soap_strdup(soap, tp->name); /* check EOM */ + a->data = soap_strdup(soap, tp->value); /* check EOM */ + a->wide = NULL; + soap->dom->atts = a; + tp->visible = 0; + } + } + return SOAP_OK; + } +#endif +/**/ + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible) + { if (soap_send(soap, " ") || soap_send(soap, tp->name)) + return soap->error; + if (tp->visible == 2 && tp->value) + if (soap_send_raw(soap, "=\"", 2) + || soap_string_out(soap, tp->value, 1) + || soap_send_raw(soap, "\"", 1)) + return soap->error; + tp->visible = 0; + } + } + if (tag) + { soap->level--; +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { if (soap_send_raw(soap, ">", 1) + || soap_element_end_out(soap, tag)) + return soap->error; + return SOAP_OK; + } +#endif + return soap_send_raw(soap, "/>", 2); + } + return soap_send_raw(soap, ">", 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_end_out(struct soap *soap, const char *tag) +{ if (*tag == '-') + return SOAP_OK; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element ending tag='%s'\n", tag)); +/**/ +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { if (soap->dom->prnt) + soap->dom = soap->dom->prnt; + return SOAP_OK; + } +#endif +/**/ + soap->level--; + if (soap_send_raw(soap, "error; + return soap_send_raw(soap, ">", 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_ref(struct soap *soap, const char *tag, int id, int href) +{ register int n = 0; + if (soap->version == 2) + n = 1; + sprintf(soap->href, "#_%d", href); + return soap_element_href(soap, tag, id, "href" + n, soap->href + n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_href(struct soap *soap, const char *tag, int id, const char *ref, const char *val) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element '%s' reference %s='%s'\n", tag, ref, val)); + if (soap_element(soap, tag, id, NULL) + || soap_attribute(soap, ref, val) + || soap_element_start_end_out(soap, tag)) + return soap->error; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_null(struct soap *soap, const char *tag, int id, const char *type) +{ struct soap_attribute *tp; + for (tp = soap->attributes; tp; tp = tp->next) + if (tp->visible) + break; + if (tp || (soap->version == 2 && soap->position > 0) || id > 0 || (soap->mode & SOAP_XML_NIL)) + { if (soap_element(soap, tag, id, type)) + return soap->error; + if (soap->part != SOAP_IN_HEADER && soap->encodingStyle) + if (soap_attribute(soap, "xsi:nil", "true")) + return soap->error; + return soap_element_start_end_out(soap, tag); + } + soap->null = 1; + soap->position = 0; + soap->mustUnderstand = 0; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_id(struct soap *soap, const char *tag, int id, const void *p, const struct soap_array *a, int n, const char *type, int t) +{ if (!p || (a && !a->__ptr)) + { soap_element_null(soap, tag, id, type); + return -1; + } +#ifndef WITH_NOIDREF + if (soap->mode & SOAP_XML_TREE) + return 0; + if (id < 0) + { struct soap_plist *pp; + if (a) + id = soap_array_pointer_lookup(soap, p, a, n, t, &pp); + else + id = soap_pointer_lookup(soap, p, t, &pp); + if (id) + { if (soap_is_embedded(soap, pp)) + { soap_element_ref(soap, tag, 0, id); + return -1; + } + if (soap_is_single(soap, pp)) + return 0; + soap_set_embedded(soap, pp); + } + } + return id; +#else + return 0; +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_result(struct soap *soap, const char *tag) +{ if (soap->version == 2 && soap->encodingStyle) + if (soap_element(soap, "SOAP-RPC:result", 0, NULL) + || soap_attribute(soap, "xmlns:SOAP-RPC", soap_rpc) + || soap_element_start_end_out(soap, NULL) + || soap_string_out(soap, tag, 0) + || soap_element_end_out(soap, "SOAP-RPC:result")) + return soap->error; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_attribute(struct soap *soap, const char *name, const char *value) +{ +/**/ +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { register struct soap_dom_attribute *a = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); + a->next = soap->dom->atts; + a->nstr = NULL; + a->name = soap_strdup(soap, name); /* check EOM */ + a->data = soap_strdup(soap, value); /* check EOM */ + a->wide = NULL; + soap->dom->atts = a; + return SOAP_OK; + } +#endif +/**/ +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { if (soap_set_attr(soap, name, value)) + return soap->error; + } + else +#endif + { if (soap_send(soap, " ") || soap_send(soap, name)) + return soap->error; + if (value) + if (soap_send_raw(soap, "=\"", 2) + || soap_string_out(soap, value, 1) + || soap_send_raw(soap, "\"", 1)) + return soap->error; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_begin_in(struct soap *soap, const char *tag, int nillable) +{ if (!soap_peek_element(soap)) + { if (soap->other) + return soap->error = SOAP_TAG_MISMATCH; + if (tag && *tag == '-') + return SOAP_OK; + if (!(soap->error = soap_match_tag(soap, soap->tag, tag))) + { soap->peeked = 0; + if (soap->body) + soap->level++; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:"" )); + if (!nillable && soap->null && (soap->mode & SOAP_XML_STRICT)) + return soap->error = SOAP_NULL; + } + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_end_in(struct soap *soap, const char *tag) +{ register soap_wchar c; + register char *s; + register const char *t; + register int n = 0; + if (tag && *tag == '-') + return SOAP_OK; + soap->level--; + soap_pop_namespace(soap); + if (soap->error == SOAP_NO_TAG) + soap->error = SOAP_OK; + if (soap->peeked && *soap->tag) + n++; + soap->peeked = 0; + do + { while (((c = soap_get(soap)) != SOAP_TT)) + { if ((int)c == EOF) + return soap->error = SOAP_EOF; + if (c == SOAP_LT) + n++; + } + } while (n--); + s = soap->tag; + do c = soap_get(soap); + while (soap_blank(c)); + do + { *s++ = (char)c; + c = soap_get(soap); + } while (soap_notblank(c)); + *s = '\0'; + if ((int)c == EOF) + return soap->error = SOAP_EOF; + while (soap_blank(c)) + c = soap_get(soap); + if (c != SOAP_GT) + return soap->error = SOAP_SYNTAX_ERROR; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:"")); + if (!tag) + return SOAP_OK; + if ((s = strchr(soap->tag, ':'))) + s++; + else + s = soap->tag; + if ((t = strchr(tag, ':'))) + t++; + else + t = tag; + if (!SOAP_STRCMP(s, t)) + return SOAP_OK; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element tag name does not match\n")); + return soap->error = SOAP_SYNTAX_ERROR; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char * +SOAP_FMAC2 +soap_attr_value(struct soap *soap, const char *name, int flag) +{ register struct soap_attribute *tp; + for (tp = soap->attributes; tp; tp = tp->next) + if (!soap_match_tag(soap, tp->name, name)) + break; + if (tp && tp->visible == 2) + { if (flag == 2 && (soap->mode & SOAP_XML_STRICT)) + soap->error = SOAP_PROHIBITED; + else + return tp->value; + } + else if (flag == 1 && (soap->mode & SOAP_XML_STRICT)) + soap->error = SOAP_REQUIRED; + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_attr(struct soap *soap, const char *name, const char *value) +{ register struct soap_attribute *tp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set attribute %s='%s'\n", name, value?value:"")); + for (tp = soap->attributes; tp; tp = tp->next) + if (!strcmp(tp->name, name)) + break; + if (!tp) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute %s\n", name)); + if (!(tp = (struct soap_attribute*)SOAP_MALLOC(sizeof(struct soap_attribute) + strlen(name)))) + return soap->error = SOAP_EOM; + tp->ns = NULL; +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { struct soap_attribute **tpp = &soap->attributes; + const char *s = strchr(name, ':'); + if (!strncmp(name, "xmlns", 5)) + { for (; *tpp; tpp = &(*tpp)->next) + if (strncmp((*tpp)->name, "xmlns", 5) || strcmp((*tpp)->name + 5, name + 5) > 0) + break; + } + else if (!s) + { for (; *tpp; tpp = &(*tpp)->next) + if (strncmp((*tpp)->name, "xmlns", 5) && ((*tpp)->ns || strcmp((*tpp)->name, name) > 0)) + break; + } + else + { int k; + for (; *tpp; tpp = &(*tpp)->next) + { if (!strncmp((*tpp)->name, "xmlns:", 6) && !strncmp((*tpp)->name + 6, name, s - name) && !(*tpp)->name[6 + s - name]) + { if (!tp->ns) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Canonicalization: prefix %s=%p(%s)\n", name, (*tpp)->ns, (*tpp)->ns)); + tp->ns = (*tpp)->ns; + } + } + else if (strncmp((*tpp)->name, "xmlns", 5) && (*tpp)->ns && tp->ns && ((k = strcmp((*tpp)->ns, tp->ns)) > 0 || (!k && strcmp((*tpp)->name, name) > 0))) + break; + } + } + tp->next = *tpp; + *tpp = tp; + } + else +#endif + { tp->next = soap->attributes; + soap->attributes = tp; + } + strcpy(tp->name, name); + tp->value = NULL; + } + else if (value && tp->value && tp->size <= strlen(value)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute value of %s (free %p)\n", name, tp->value)); + SOAP_FREE(tp->value); + tp->value = NULL; + tp->ns = NULL; + } + if (value) + { if (!tp->value) + { tp->size = strlen(value) + 1; + if (!(tp->value = (char*)SOAP_MALLOC(tp->size))) + return soap->error = SOAP_EOM; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute value of %s (%p)\n", tp->name, tp->value)); + } + strcpy(tp->value, value); + if (!strncmp(tp->name, "xmlns:", 6)) + tp->ns = tp->value; + tp->visible = 2; + } + else + tp->visible = 1; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_clr_attr(struct soap *soap) +{ register struct soap_attribute *tp; +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { while (soap->attributes) + { tp = soap->attributes->next; + SOAP_FREE(soap->attributes->value); + SOAP_FREE(soap->attributes); + soap->attributes = tp; + } + } + else +#endif + { for (tp = soap->attributes; tp; tp = tp->next) + tp->visible = 0; + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +static int +soap_getattrval(struct soap *soap, char *s, size_t n, soap_wchar d) +{ size_t i; + soap_wchar c; + for (i = 0; i < n; i++) + { c = soap_getutf8(soap); + switch (c) + { + case SOAP_TT: + *s++ = '<'; + soap_unget(soap, '/'); + break; + case SOAP_LT: + *s++ = '<'; + break; + case SOAP_GT: + if (d == ' ') + { soap_unget(soap, c); + *s = '\0'; + return SOAP_OK; + } + *s++ = '>'; + break; + case SOAP_QT: + if (c == d) + { *s = '\0'; + return SOAP_OK; + } + *s++ = '"'; + break; + case SOAP_AP: + if (c == d) + { *s = '\0'; + return SOAP_OK; + } + *s++ = '\''; + break; + case '\t': + case '\n': + case '\r': + case ' ': + case '/': + if (d == ' ') + { soap_unget(soap, c); + *s = '\0'; + return SOAP_OK; + } + default: + if ((int)c == EOF) + return soap->error = SOAP_EOF; + *s++ = (char)c; + } + } + return soap->error = SOAP_EOM; +} +#endif + +/******************************************************************************/ +#ifdef WITH_FAST +#ifndef PALM_2 +static int +soap_append_lab(struct soap *soap, const char *s, size_t n) +{ if (soap->labidx + n >= soap->lablen) + { register char *t = soap->labbuf; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enlarging look-aside buffer to append data, old size=%lu", (unsigned long)soap->lablen)); + if (soap->lablen == 0) + soap->lablen = SOAP_LABLEN; + while (soap->labidx + n >= soap->lablen) + soap->lablen <<= 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, ", new size=%lu\n", (unsigned long)soap->lablen)); + soap->labbuf = (char*)SOAP_MALLOC(soap->lablen); + if (!soap->labbuf) + { if (t) + free(t); + return soap->error = SOAP_EOM; + } + if (t && soap->labidx) + { memcpy(soap->labbuf, t, soap->labidx); + free(t); + } + } + if (s) + { memcpy(soap->labbuf + soap->labidx, s, n); + soap->labidx += n; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_peek_element(struct soap *soap) +{ register struct soap_attribute *tp; + const char *t; + register char *s; + register soap_wchar c; + register int i; + if (soap->peeked) + { if (!*soap->tag) + return soap->error = SOAP_NO_TAG; + return SOAP_OK; + } + soap->peeked = 1; + for (;;) + { c = soap_getutf8(soap); + if (c == SOAP_BOM) + c = soap_getutf8(soap); + while (soap_blank(c)) + c = soap_getutf8(soap); + if ((int)c == EOF) + return soap->error = SOAP_EOF; + if (c != SOAP_LT) + { *soap->tag = '\0'; + soap_unget(soap, c); + return soap->error = SOAP_NO_TAG; + } + s = soap->tag; + do c = soap_get(soap); + while (soap_blank(c)); + i = sizeof(soap->tag); + while (c != '/' && soap_notblank(c)) + { if (--i > 0) + *s++ = (char)c; + c = soap_get(soap); + } + while (soap_blank(c)) + c = soap_get(soap); + *s = '\0'; + if (*soap->tag != '?') + break; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "XML PI <%s?>\n", soap->tag)); + while ((int)c != EOF && c != SOAP_GT && c != '?') + { s = soap->tmpbuf; + i = sizeof(soap->tmpbuf) - 2; + while (c != '=' && c != SOAP_GT && c != '?' && soap_notblank(c)) + { if (--i > 0) + *s++ = (char)c; + c = soap_get(soap); + } + while (soap_blank(c)) + c = soap_get(soap); + if (c == '=') + { *s++ = '='; + do c = soap_get(soap); + while (soap_blank(c)); + if (c != SOAP_QT && c != SOAP_AP) + { soap_unget(soap, c); + c = ' '; /* blank delimiter */ + } + if (soap_getattrval(soap, s, i, c) == SOAP_EOM) + while (soap_getattrval(soap, soap->tmpbuf, sizeof(soap->tmpbuf), c) == SOAP_EOM) + ; + else if (!strcmp(soap->tag, "?xml") && (!soap_tag_cmp(soap->tmpbuf, "encoding=iso-8859-1") || !soap_tag_cmp(soap->tmpbuf, "encoding=latin1"))) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "XML latin1 encoding\n")); + soap->mode |= SOAP_ENC_LATIN; + } + } + do c = soap_get(soap); + while (soap_blank(c)); + } + } + soap->id[0] = '\0'; + soap->href[0] = '\0'; + soap->type[0] = '\0'; + soap->arrayType[0] = '\0'; + soap->arraySize[0] = '\0'; + soap->arrayOffset[0] = '\0'; + soap->other = 0; + soap->root = -1; + soap->position = 0; + soap->null = 0; + soap->mustUnderstand = 0; + soap_clr_attr(soap); + while ((int)c != EOF && c != SOAP_GT && c != '/') + { s = soap->tmpbuf; + i = sizeof(soap->tmpbuf); + while (c != '=' && c != '/' && soap_notblank(c)) + { if (--i > 0) + *s++ = (char)c; + c = soap_get(soap); + } + *s = '\0'; + if (i == sizeof(soap->tmpbuf)) + return soap->error = SOAP_SYNTAX_ERROR; + if (!strncmp(soap->tmpbuf, "xmlns:", 6)) + { soap->tmpbuf[5] = '\0'; + t = soap->tmpbuf + 6; + } + else if (!strcmp(soap->tmpbuf, "xmlns")) + t = SOAP_STR_EOS; + else + t = NULL; + for (tp = soap->attributes; tp; tp = tp->next) + if (!SOAP_STRCMP(tp->name, soap->tmpbuf)) + break; + if (!tp) + { tp = (struct soap_attribute*)SOAP_MALLOC(sizeof(struct soap_attribute) + strlen(soap->tmpbuf)); + if (!tp) + return soap->error = SOAP_EOM; + strcpy(tp->name, soap->tmpbuf); + tp->value = NULL; + tp->size = 0; + tp->next = soap->attributes; + soap->attributes = tp; + } + while (soap_blank(c)) + c = soap_get(soap); + if (c == '=') + { do c = soap_get(soap); + while (soap_blank(c)); + if (c != SOAP_QT && c != SOAP_AP) + { soap_unget(soap, c); + c = ' '; /* blank delimiter */ + } + if (soap_getattrval(soap, tp->value, tp->size, c)) + { +#ifdef WITH_FAST + if (soap->error != SOAP_EOM) + return soap->error; + soap->error = SOAP_OK; + soap->labidx = 0; + if (soap_append_lab(soap, tp->value, tp->size)) + return soap->error; + SOAP_FREE(tp->value); + for (;;) + { if (soap_getattrval(soap, soap->labbuf + soap->labidx, soap->lablen - soap->labidx, c)) + { if (soap->error != SOAP_EOM) + return soap->error; + soap->error = SOAP_OK; + soap->labidx = soap->lablen; + if (soap_append_lab(soap, NULL, 0)) + return soap->error; + } + else + break; + } + tp->size = soap->lablen; + if (!(tp->value = (char*)SOAP_MALLOC(tp->size))) + return soap->error = SOAP_EOM; + memcpy(tp->value, soap->labbuf, soap->lablen); +#else + size_t n; + if (soap->error != SOAP_EOM) + return soap->error; + soap->error = SOAP_OK; + if (soap_new_block(soap)) + return soap->error; + for (;;) + { if (!(s = (char*)soap_push_block(soap, SOAP_BLKLEN))) + return soap->error; + if (soap_getattrval(soap, s, SOAP_BLKLEN, c)) + { if (soap->error != SOAP_EOM) + return soap->error; + soap->error = SOAP_OK; + } + else + break; + } + n = tp->size + soap->blist->size; + if (!(s = (char*)SOAP_MALLOC(n))) + return soap->error = SOAP_EOM; + if (tp->value) + { memcpy(s, tp->value, tp->size); + SOAP_FREE(tp->value); + } + soap_save_block(soap, s + tp->size, 0); + tp->value = s; + tp->size = n; +#endif + } + do c = soap_get(soap); + while (soap_blank(c)); + tp->visible = 2; /* seen this attribute w/ value */ + } + else + tp->visible = 1; /* seen this attribute w/o value */ + if (t && tp->value) + { if (soap_push_namespace(soap, t, tp->value)) + return soap->error; + tp->visible = 0; + } + } + if ((int)c == EOF) + return soap->error = SOAP_EOF; + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible && tp->value) + { if (!strcmp(tp->name, "id")) + { *soap->id = '#'; + strncpy(soap->id + 1, tp->value, sizeof(soap->id) - 2); + soap->id[sizeof(soap->id)-1] = '\0'; + } + else if (!strcmp(tp->name, "href")) + { strncpy(soap->href, tp->value, sizeof(soap->href) - 1); + soap->href[sizeof(soap->href)-1] = '\0'; + } + else if ((soap->version == 2 || (soap->mode & SOAP_XML_GRAPH)) && !strcmp(tp->name, "ref")) + { *soap->href = '#'; + strncpy(soap->href + 1, tp->value, sizeof(soap->href) - 2); + soap->href[sizeof(soap->href)-1] = '\0'; + } + else if (!soap_match_tag(soap, tp->name, "xsi:type")) + { strncpy(soap->type, tp->value, sizeof(soap->type) - 1); + soap->type[sizeof(soap->type)-1] = '\0'; + } + else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:arrayType")) + { s = soap_strrchr(tp->value, '['); + if (s && (size_t)(s - tp->value) < sizeof(soap->arrayType)) + { strncpy(soap->arrayType, tp->value, s - tp->value); + soap->arrayType[s - tp->value] = '\0'; + strncpy(soap->arraySize, s, sizeof(soap->arraySize) - 1); + } + else + strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1); + soap->arraySize[sizeof(soap->arrayType)-1] = '\0'; + soap->arrayType[sizeof(soap->arrayType)-1] = '\0'; + } + else if (soap->version == 2 && !soap_match_tag(soap, tp->name, "SOAP-ENC:itemType")) + strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1); + else if (soap->version == 2 && !soap_match_tag(soap, tp->name, "SOAP-ENC:arraySize")) + strncpy(soap->arraySize, tp->value, sizeof(soap->arraySize) - 1); + else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:offset")) + strncpy(soap->arrayOffset, tp->value, sizeof(soap->arrayOffset)); + else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:position")) + soap->position = soap_getposition(tp->value, soap->positions); + else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:root")) + soap->root = ((!strcmp(tp->value, "1") || !strcmp(tp->value, "true"))); + else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:actor") + || !soap_match_tag(soap, tp->name, "SOAP-ENV:role")) + { if ((!soap->actor || strcmp(soap->actor, tp->value)) + && strcmp(tp->value, "http://schemas.xmlsoap.org/soap/actor/next") + && strcmp(tp->value, "http://www.w3.org/2003/05/soap-envelope/role/next")) + soap->other = 1; + } + else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand") + && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true"))) + soap->mustUnderstand = 1; + else if ((!soap_match_tag(soap, tp->name, "xsi:null") + || !soap_match_tag(soap, tp->name, "xsi:nil")) + && (!strcmp(tp->value, "1") + || !strcmp(tp->value, "true"))) + soap->null = 1; + } + } + if (!(soap->body = (c != '/'))) + do c = soap_get(soap); + while (soap_blank(c)); + return soap->error = SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_retry(struct soap *soap) +{ soap->peeked = 1; + soap->error = SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_revert(struct soap *soap) +{ if (!soap->peeked) + { soap->peeked = 1; + if (soap->body) + soap->level--; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reverting last element (level=%u)\n", soap->level)); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_string_out(struct soap *soap, const char *s, int flag) +{ register const char *t; + register soap_wchar c; + register soap_wchar mask = 0xFFFFFF80UL; +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { soap->dom->data = soap_strdup(soap, s); /* check EOM */ + return SOAP_OK; + } +#endif + if (soap->mode & SOAP_C_UTFSTRING) + mask = 0; + t = s; + while ((c = *t++)) + { switch (c) + { + case 9: + if (flag) + { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, " ", 5)) + return soap->error; + s = t; + } + break; + case 10: + if (flag || !(soap->mode & SOAP_XML_CANONICAL)) + { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, " ", 5)) + return soap->error; + s = t; + } + break; + case 13: + if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, " ", 5)) + return soap->error; + s = t; + break; + case '&': + if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&", 5)) + return soap->error; + s = t; + break; + case '<': + if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "<", 4)) + return soap->error; + s = t; + break; + case '>': + if (!flag) + { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, ">", 4)) + return soap->error; + s = t; + } + break; + case '"': + if (flag) + { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, """, 6)) + return soap->error; + s = t; + } + break; + default: +#ifndef WITH_LEANER +#ifdef HAVE_MBTOWC + if (soap->mode & SOAP_C_MBSTRING) + { wchar_t wc; + register int m = mbtowc(&wc, t - 1, MB_CUR_MAX); + if (m > 0 && wc != c) + { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, wc)) + return soap->error; + s = t + m - 1; + continue; + } + } +#endif +#endif + if (c & mask) + { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned char)c)) + return soap->error; + s = t; + } + } + } + return soap_send_raw(soap, s, t - s - 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_string_in(struct soap *soap, int flag, long minlen, long maxlen) +{ register char *s; + char *t = NULL; + register size_t i; + register long l = 0; + register int n = 0; + register size_t m = 0; + register soap_wchar c; +#if !defined(WITH_LEANER) && defined(HAVE_WCTOMB) + char buf[MB_LEN_MAX > 8 ? MB_LEN_MAX : 8]; +#else + char buf[8]; +#endif + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading string content\n")); +#ifdef WITH_CDATA + if (!flag) + { register int state = 0; +#ifdef WITH_FAST + soap->labidx = 0; /* use look-aside buffer */ +#else + if (soap_new_block(soap)) + return NULL; +#endif + for (;;) + { +#ifdef WITH_FAST + register size_t k; + if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */ + return NULL; + s = soap->labbuf + soap->labidx; /* space to populate */ + k = soap->lablen - soap->labidx; /* number of bytes available */ + soap->labidx = soap->lablen; /* claim this space */ +#else + register size_t k = SOAP_BLKLEN; + if (!(s = (char*)soap_push_block(soap, k))) + return NULL; +#endif + for (i = 0; i < k; i++) + { if (m > 0) + { *s++ = *t++; /* copy multibyte characters */ + m--; + continue; + } + c = soap_getchar(soap); + if ((int)c == EOF) + goto end; + if (c >= 0x80 && !(soap->mode & SOAP_ENC_LATIN)) + { soap_unget(soap, c); + c = soap_getutf8(soap); + if (soap->mode & SOAP_C_UTFSTRING) + { if ((c & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP) + { c &= 0x7FFFFFFF; + t = buf; + if (c < 0x0800) + *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); + else + { if (c < 0x010000) + *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + else + { if (c < 0x200000) + *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + else + { if (c < 0x04000000) + *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + else + { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + } + *t++ = (char)(0x80 | (c & 0x3F)); + m = (int)(t - buf) - 1; + t = buf; + *s++ = *t++; + continue; + } + } + } + switch (state) + { case 1: + if (c == ']') + state = 4; + *s++ = c; + continue; + case 2: + if (c == '-') + state = 6; + *s++ = c; + continue; + case 3: + if (c == '?') + state = 8; + *s++ = c; + continue; + /* CDATA */ + case 4: + if (c == ']') + state = 5; + else + state = 1; + *s++ = c; + continue; + case 5: + if (c == '>') + state = 0; + else + state = 1; + *s++ = c; + continue; + /* comment */ + case 6: + if (c == '-') + state = 7; + else + state = 2; + *s++ = c; + continue; + case 7: + if (c == '>') + state = 0; + else + state = 2; + *s++ = c; + continue; + /* PI */ + case 8: + if (c == '>') + state = 0; + else + state = 3; + *s++ = c; + continue; + } + switch (c) + { + case '/': + if (n > 0) + { c = soap_getchar(soap); + if (c == '>') + n--; + soap_unget(soap, c); + } + *s++ = '/'; + break; + case '<': + c = soap_getchar(soap); + if (c == '/') + { if (n == 0) + { c = SOAP_TT; + goto end; + } + n--; + } + else if (c == '!') + { c = soap_getchar(soap); + if (c == '[') + { do c = soap_getchar(soap); + while ((int)c != EOF && c != '['); + if ((int)c == EOF) + goto end; + t = (char*)"![CDATA["; + m = 8; + state = 1; + } + else if (c == '-') + { if ((c = soap_getchar(soap)) == '-') + state = 2; + t = (char*)"!-"; + m = 2; + soap_unget(soap, c); + } + else + { t = (char*)"!"; + m = 1; + soap_unget(soap, c); + } + *s++ = '<'; + break; + } + else if (c == '?') + state = 3; + else + n++; + soap_unget(soap, c); + *s++ = '<'; + break; + case '>': + *s++ = '>'; + break; + case '"': + *s++ = '"'; + break; + default: +#ifndef WITH_LEANER +#ifdef HAVE_WCTOMB + if (soap->mode & SOAP_C_MBSTRING) + { m = wctomb(buf, c & 0x7FFFFFFF); + if (m >= 1) + { t = buf; + *s++ = *t++; + m--; + } + else + *s++ = SOAP_UNKNOWN_CHAR; + } + else +#endif +#endif + *s++ = (char)(c & 0xFF); + } + l++; + if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); + soap->error = SOAP_LENGTH; + return NULL; + } + } + } + } +#endif +#ifdef WITH_FAST + soap->labidx = 0; /* use look-aside buffer */ +#else + if (soap_new_block(soap)) + return NULL; +#endif + for (;;) + { +#ifdef WITH_FAST + register size_t k; + if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */ + return NULL; + s = soap->labbuf + soap->labidx; /* space to populate */ + k = soap->lablen - soap->labidx; /* number of bytes available */ + soap->labidx = soap->lablen; /* claim this space */ +#else + register size_t k = SOAP_BLKLEN; + if (!(s = (char*)soap_push_block(soap, k))) + return NULL; +#endif + for (i = 0; i < k; i++) + { if (m > 0) + { *s++ = *t++; /* copy multibyte characters */ + m--; + continue; + } + if (soap->mode & SOAP_C_UTFSTRING) + { if (((c = soap_get(soap)) & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP) + { c &= 0x7FFFFFFF; + t = buf; + if (c < 0x0800) + *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); + else + { if (c < 0x010000) + *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + else + { if (c < 0x200000) + *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + else + { if (c < 0x04000000) + *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + else + { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + } + *t++ = (char)(0x80 | (c & 0x3F)); + m = (int)(t - buf) - 1; + t = buf; + *s++ = *t++; + continue; + } + } + else + c = soap_getutf8(soap); + switch (c) + { + case SOAP_TT: + if (n == 0) + goto end; + n--; + *s++ = '<'; + t = (char*)"/"; + m = 1; + break; + case SOAP_LT: + n++; + *s++ = '<'; + break; + case SOAP_GT: + *s++ = '>'; + break; + case SOAP_QT: + *s++ = '"'; + break; + case SOAP_AP: + *s++ = '\''; + break; + case '/': + if (n > 0) + { c = soap_get(soap); + if (c == SOAP_GT) + n--; + soap_unget(soap, c); + } + *s++ = '/'; + break; + case '<' | 0x80000000: + if (flag) + *s++ = '<'; + else + { *s++ = '&'; + t = (char*)"lt;"; + m = 3; + } + break; + case '>' | 0x80000000: + if (flag) + *s++ = '>'; + else + { *s++ = '&'; + t = (char*)"gt;"; + m = 3; + } + break; + case '&' | 0x80000000: + if (flag) + *s++ = '&'; + else + { *s++ = '&'; + t = (char*)"amp;"; + m = 4; + } + break; + case '"' | 0x80000000: + if (flag) + *s++ = '"'; + else + { *s++ = '&'; + t = (char*)"quot;"; + m = 5; + } + break; + case '\'' | 0x80000000: + if (flag) + *s++ = '\''; + else + { *s++ = '&'; + t = (char*)"apos;"; + m = 5; + } + break; + default: + if ((int)c == EOF) + goto end; +#ifndef WITH_LEANER +#ifdef HAVE_WCTOMB + if (soap->mode & SOAP_C_MBSTRING) + { m = wctomb(buf, c & 0x7FFFFFFF); + if (m >= 1) + { t = buf; + *s++ = *t++; + m--; + } + else + *s++ = SOAP_UNKNOWN_CHAR; + } + else +#endif +#endif + *s++ = (char)(c & 0xFF); + } + l++; + if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); + soap->error = SOAP_LENGTH; + return NULL; + } + } + } +end: + soap_unget(soap, c); + *s = '\0'; +#ifdef WITH_FAST + t = soap_strdup(soap, soap->labbuf); +#else + soap_size_block(soap, i+1); + t = soap_save_block(soap, NULL, 0); +#endif + if ((soap->mode & SOAP_XML_STRICT) && l < minlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen)); + soap->error = SOAP_LENGTH; + return NULL; + } + if (flag == 2) + if (soap_s2QName(soap, t, &t)) + return NULL; + if (soap->peeked && *soap->tag) + { soap->peeked = 0; + if (soap_element_end_in(soap, NULL)) + return NULL; + } + return t; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_wstring_out(struct soap *soap, const wchar_t *s, int flag) +{ const char *t; + char tmp; + register soap_wchar c; +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { soap->dom->wide = NULL; /* soap_malloc() ??? */ + return SOAP_OK; + } +#endif + while ((c = *s++)) + { switch (c) + { + case 9: + if (flag) + t = " "; + else + t = "\t"; + break; + case 10: + if (flag || !(soap->mode & SOAP_XML_CANONICAL)) + t = " "; + else + t = "\n"; + break; + case 13: + t = " "; + break; + case '&': + t = "&"; + break; + case '<': + t = "<"; + break; + case '>': + if (flag) + t = ">"; + else + t = ">"; + break; + case '"': + if (flag) + t = """; + else + t = "\""; + break; + default: + if (c > 0 && c < 0x80) + { tmp = (char)c; + if (soap_send_raw(soap, &tmp, 1)) + return soap->error; + } + else if (soap_pututf8(soap, (unsigned long)c)) + return soap->error; + continue; + } + if (soap_send(soap, t)) + return soap->error; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +wchar_t * +SOAP_FMAC2 +soap_wstring_in(struct soap *soap, int flag, long minlen, long maxlen) +{ wchar_t *s; + register int i, n = 0; + register long l = 0; + register soap_wchar c; + const char *t = NULL; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading wide string content\n")); + if (soap->peeked && *soap->tag) + { n = 1; + soap->peeked = 0; + } + if (soap_new_block(soap)) + return NULL; + for (;;) + { if (!(s = (wchar_t*)soap_push_block(soap, sizeof(wchar_t)*SOAP_BLKLEN))) + return NULL; + for (i = 0; i < SOAP_BLKLEN; i++) + { if (t) + { *s++ = (wchar_t)*t++; + if (!*t) + t = NULL; + continue; + } + c = soap_getutf8(soap); + switch (c) + { + case SOAP_TT: + if (n == 0) + goto end; + n--; + *s++ = '<'; + soap_unget(soap, '/'); + break; + case SOAP_LT: + n++; + *s++ = '<'; + break; + case SOAP_GT: + *s++ = '>'; + break; + case SOAP_QT: + *s++ = '"'; + break; + case SOAP_AP: + *s++ = '\''; + break; + case '/': + if (n > 0) + { c = soap_getutf8(soap); + if (c == SOAP_GT) + n--; + soap_unget(soap, c); + } + *s++ = '/'; + break; + case '<': + if (flag) + *s++ = (soap_wchar)'<'; + else + { *s++ = (soap_wchar)'&'; + t = "lt;"; + } + break; + case '>': + if (flag) + *s++ = (soap_wchar)'>'; + else + { *s++ = (soap_wchar)'&'; + t = "gt;"; + } + break; + case '"': + if (flag) + *s++ = (soap_wchar)'"'; + else + { *s++ = (soap_wchar)'&'; + t = "quot;"; + } + break; + default: + if ((int)c == EOF) + goto end; + *s++ = (wchar_t)c & 0x7FFFFFFF; + } + l++; + if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); + soap->error = SOAP_LENGTH; + return NULL; + } + } + } +end: + soap_unget(soap, c); + *s = '\0'; + soap_size_block(soap, sizeof(wchar_t) * (i + 1)); + if ((soap->mode & SOAP_XML_STRICT) && l < minlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen)); + soap->error = SOAP_LENGTH; + return NULL; + } + if (soap->peeked && *soap->tag) + { soap->peeked = 0; + if (soap_element_end_in(soap, NULL)) + return NULL; + } + return (wchar_t*)soap_save_block(soap, NULL, 0); +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_int2s(struct soap *soap, int n) +{ return soap_long2s(soap, (long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outint(struct soap *soap, const char *tag, int id, const int *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_long2s(soap, (long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2int(struct soap *soap, const char *s, int *p) +{ if (s) + { char *r; + *p = (int)soap_strtol(s, &r, 10); + if (*r) + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int * +SOAP_FMAC2 +soap_inint(struct soap *soap, const char *tag, int *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":int") + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (int*)soap_id_enter(soap, soap->id, p, t, sizeof(int), 0, NULL, NULL, NULL); + if (p) + { if (soap_s2int(soap, soap_value(soap), p)) + return NULL; + } + p = (int*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(int), 0, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_long2s(struct soap *soap, long n) +{ sprintf(soap->tmpbuf, "%ld", n); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outlong(struct soap *soap, const char *tag, int id, const long *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_long2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2long(struct soap *soap, const char *s, long *p) +{ if (s) + { char *r; + *p = soap_strtol(s, &r, 10); + if (*r) + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +long * +SOAP_FMAC2 +soap_inlong(struct soap *soap, const char *tag, long *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":int") + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (long*)soap_id_enter(soap, soap->id, p, t, sizeof(long), 0, NULL, NULL, NULL); + if (p) + { if (soap_s2long(soap, soap_value(soap), p)) + return NULL; + } + p = (long*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(long), 0, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_LONG642s(struct soap *soap, LONG64 n) +{ sprintf(soap->tmpbuf, SOAP_LONG_FORMAT, n); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outLONG64(struct soap *soap, const char *tag, int id, const LONG64 *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_LONG642s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2LONG64(struct soap *soap, const char *s, LONG64 *p) +{ if (s && sscanf(s, SOAP_LONG_FORMAT, p) != 1) + soap->error = SOAP_TYPE; + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +LONG64 * +SOAP_FMAC2 +soap_inLONG64(struct soap *soap, const char *tag, LONG64 *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":integer") + && soap_match_tag(soap, soap->type, ":positiveInteger") + && soap_match_tag(soap, soap->type, ":negativeInteger") + && soap_match_tag(soap, soap->type, ":nonPositiveInteger") + && soap_match_tag(soap, soap->type, ":nonNegativeInteger") + && soap_match_tag(soap, soap->type, ":long") + && soap_match_tag(soap, soap->type, ":int") + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (LONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(LONG64), 0, NULL, NULL, NULL); + if (p) + { if (soap_s2LONG64(soap, soap_value(soap), p)) + return NULL; + } + p = (LONG64*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(LONG64), 0, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_byte2s(struct soap *soap, char n) +{ return soap_long2s(soap, (long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outbyte(struct soap *soap, const char *tag, int id, const char *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_long2s(soap, (long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2byte(struct soap *soap, const char *s, char *p) +{ if (s) + { long n; + char *r; + n = soap_strtol(s, &r, 10); + if (*r || n < -128 || n > 127) + soap->error = SOAP_TYPE; + *p = (char)n; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_inbyte(struct soap *soap, const char *tag, char *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (char*)soap_id_enter(soap, soap->id, p, t, sizeof(char), 0, NULL, NULL, NULL); + if (p) + { if (soap_s2byte(soap, soap_value(soap), p)) + return NULL; + } + p = (char*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(char), 0, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_short2s(struct soap *soap, short n) +{ return soap_long2s(soap, (long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outshort(struct soap *soap, const char *tag, int id, const short *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_long2s(soap, (long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2short(struct soap *soap, const char *s, short *p) +{ if (s) + { long n; + char *r; + n = soap_strtol(s, &r, 10); + if (*r || n < -32768 || n > 32767) + soap->error = SOAP_TYPE; + *p = (short)n; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +short * +SOAP_FMAC2 +soap_inshort(struct soap *soap, const char *tag, short *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (short*)soap_id_enter(soap, soap->id, p, t, sizeof(short), 0, NULL, NULL, NULL); + if (p) + { if (soap_s2short(soap, soap_value(soap), p)) + return NULL; + } + p = (short*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(short), 0, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_float2s(struct soap *soap, float n) +{ const char *s; + if (soap_isnan((double)n)) + s = "NaN"; + else if (soap_ispinff(n)) + s = "INF"; + else if (soap_isninff(n)) + s = "-INF"; + else + { sprintf(soap->tmpbuf, soap->float_format, n); + s = soap->tmpbuf; + } + return s; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outfloat(struct soap *soap, const char *tag, int id, const float *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_float2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2float(struct soap *soap, const char *s, float *p) +{ if (s) + { if (!soap_tag_cmp(s, "INF")) + *p = FLT_PINFTY; + else if (!soap_tag_cmp(s, "+INF")) + *p = FLT_PINFTY; + else if (!soap_tag_cmp(s, "-INF")) + *p = FLT_NINFTY; + else if (!soap_tag_cmp(s, "NaN")) + *p = FLT_NAN; + else + { +#if defined(HAVE_STRTOF) + char *r; + *p = strtof(s, &r); + if (*r) +#elif defined(HAVE_STRTOD) + char *r; + *p = (float)strtod(s, &r); + if (*r) +#endif +#ifdef HAVE_SSCANF + if (sscanf(s, soap->float_format, p) != 1) + soap->error = SOAP_TYPE; +#else + soap->error = SOAP_TYPE; +#endif + } + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static int soap_isnumeric(struct soap *soap, const char *type) +{ if (soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":float") + && soap_match_tag(soap, soap->type, ":double") + && soap_match_tag(soap, soap->type, ":decimal") + && soap_match_tag(soap, soap->type, ":integer") + && soap_match_tag(soap, soap->type, ":positiveInteger") + && soap_match_tag(soap, soap->type, ":negativeInteger") + && soap_match_tag(soap, soap->type, ":nonPositiveInteger") + && soap_match_tag(soap, soap->type, ":nonNegativeInteger") + && soap_match_tag(soap, soap->type, ":long") + && soap_match_tag(soap, soap->type, ":int") + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte") + && soap_match_tag(soap, soap->type, ":unsignedLong") + && soap_match_tag(soap, soap->type, ":unsignedInt") + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return SOAP_ERR; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +float * +SOAP_FMAC2 +soap_infloat(struct soap *soap, const char *tag, float *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type != '\0' && soap_isnumeric(soap, type)) + return NULL; +#endif + p = (float*)soap_id_enter(soap, soap->id, p, t, sizeof(float), 0, NULL, NULL, NULL); + if (p) + { if (soap_s2float(soap, soap_value(soap), p)) + return NULL; + } + p = (float*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(float), 0, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_double2s(struct soap *soap, double n) +{ const char *s; + if (soap_isnan(n)) + s = "NaN"; + else if (soap_ispinfd(n)) + s = "INF"; + else if (soap_isninfd(n)) + s = "-INF"; + else + { sprintf(soap->tmpbuf, soap->double_format, n); + s = soap->tmpbuf; + } + return s; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outdouble(struct soap *soap, const char *tag, int id, const double *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_double2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2double(struct soap *soap, const char *s, double *p) +{ if (s) + { if (!soap_tag_cmp(s, "INF")) + *p = DBL_PINFTY; + else if (!soap_tag_cmp(s, "+INF")) + *p = DBL_PINFTY; + else if (!soap_tag_cmp(s, "-INF")) + *p = DBL_NINFTY; + else if (!soap_tag_cmp(s, "NaN")) + *p = DBL_NAN; + else + { +#ifdef HAVE_STRTOD + char *r; + *p = strtod(s, &r); + if (*r) +#endif +#ifdef HAVE_SSCANF + if (sscanf(s, soap->double_format, p) != 1) + soap->error = SOAP_TYPE; +#else + soap->error = SOAP_TYPE; +#endif + } + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +double * +SOAP_FMAC2 +soap_indouble(struct soap *soap, const char *tag, double *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type != '\0' && soap_isnumeric(soap, type)) + return NULL; +#endif + p = (double*)soap_id_enter(soap, soap->id, p, t, sizeof(double), 0, NULL, NULL, NULL); + if (p) + { if (soap_s2double(soap, soap_value(soap), p)) + return NULL; + } + p = (double*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(double), 0, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_unsignedByte2s(struct soap *soap, unsigned char n) +{ return soap_unsignedLong2s(soap, (unsigned long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outunsignedByte(struct soap *soap, const char *tag, int id, const unsigned char *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2unsignedByte(struct soap *soap, const char *s, unsigned char *p) +{ if (s) + { unsigned long n; + char *r; + n = soap_strtoul(s, &r, 10); + if (*r || n > 255) + soap->error = SOAP_TYPE; + *p = (unsigned char)n; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +unsigned char * +SOAP_FMAC2 +soap_inunsignedByte(struct soap *soap, const char *tag, unsigned char *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (unsigned char*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned char), 0, NULL, NULL, NULL); + if (p) + { if (soap_s2unsignedByte(soap, soap_value(soap), p)) + return NULL; + } + p = (unsigned char*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(unsigned char), 0, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_unsignedShort2s(struct soap *soap, unsigned short n) +{ return soap_unsignedLong2s(soap, (unsigned long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outunsignedShort(struct soap *soap, const char *tag, int id, const unsigned short *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2unsignedShort(struct soap *soap, const char *s, unsigned short *p) +{ if (s) + { unsigned long n; + char *r; + n = soap_strtoul(s, &r, 10); + if (*r || n > 65535) + soap->error = SOAP_TYPE; + *p = (unsigned short)n; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +unsigned short * +SOAP_FMAC2 +soap_inunsignedShort(struct soap *soap, const char *tag, unsigned short *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (unsigned short*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned short), 0, NULL, NULL, NULL); + if (p) + { if (soap_s2unsignedShort(soap, soap_value(soap), p)) + return NULL; + } + p = (unsigned short*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(unsigned short), 0, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_unsignedInt2s(struct soap *soap, unsigned int n) +{ return soap_unsignedLong2s(soap, (unsigned long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outunsignedInt(struct soap *soap, const char *tag, int id, const unsigned int *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2unsignedInt(struct soap *soap, const char *s, unsigned int *p) +{ if (s) + { char *r; + *p = (unsigned int)soap_strtoul(s, &r, 10); + if (*r) + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +unsigned int * +SOAP_FMAC2 +soap_inunsignedInt(struct soap *soap, const char *tag, unsigned int *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":unsignedInt") + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (unsigned int*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned int), 0, NULL, NULL, NULL); + if (p) + { if (soap_s2unsignedInt(soap, soap_value(soap), p)) + return NULL; + } + p = (unsigned int*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(unsigned int), 0, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_unsignedLong2s(struct soap *soap, unsigned long n) +{ sprintf(soap->tmpbuf, "%lu", n); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outunsignedLong(struct soap *soap, const char *tag, int id, const unsigned long *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_unsignedLong2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2unsignedLong(struct soap *soap, const char *s, unsigned long *p) +{ if (s) + { char *r; + *p = soap_strtoul(s, &r, 10); + if (*r) + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +unsigned long * +SOAP_FMAC2 +soap_inunsignedLong(struct soap *soap, const char *tag, unsigned long *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":unsignedInt") + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (unsigned long*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned long), 0, NULL, NULL, NULL); + if (p) + { if (soap_s2unsignedLong(soap, soap_value(soap), p)) + return NULL; + } + p = (unsigned long*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(unsigned long), 0, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_ULONG642s(struct soap *soap, ULONG64 n) +{ sprintf(soap->tmpbuf, SOAP_ULONG_FORMAT, n); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outULONG64(struct soap *soap, const char *tag, int id, const ULONG64 *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_ULONG642s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2ULONG64(struct soap *soap, const char *s, ULONG64 *p) +{ if (s && sscanf(s, SOAP_ULONG_FORMAT, p) != 1) + soap->error = SOAP_TYPE; + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +ULONG64 * +SOAP_FMAC2 +soap_inULONG64(struct soap *soap, const char *tag, ULONG64 *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":positiveInteger") + && soap_match_tag(soap, soap->type, ":nonNegativeInteger") + && soap_match_tag(soap, soap->type, ":unsignedLong") + && soap_match_tag(soap, soap->type, ":unsignedInt") + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } + p = (ULONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(ULONG64), 0, NULL, NULL, NULL); + if (p) + { if (soap_s2ULONG64(soap, soap_value(soap), p)) + return NULL; + } + p = (ULONG64*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(ULONG64), 0, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2string(struct soap *soap, const char *s, char **t) +{ *t = NULL; + if (s && !(*t = soap_strdup(soap, s))) + soap->error = SOAP_EOM; + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2QName(struct soap *soap, const char *s, char **t) +{ if (s) + { struct soap_nlist *np; + const char *p; + if (!strncmp(s, "xml:", 4)) + { *t = soap_strdup(soap, s); + return SOAP_OK; + } + np = soap->nlist; + p = strchr(s, ':'); + if (p) + { register int n = p - s; + while (np && (strncmp(np->id, s, n) || np->id[n])) + np = np->next; + p++; + } + else + { while (np && *np->id) + np = np->next; + p = s; + } + if (np) + { if (np->index >= 0 && soap->local_namespaces) + { register const char *q = soap->local_namespaces[np->index].id; + if (q) + { if ((*t = (char*)soap_malloc(soap, strlen(p) + strlen(q) + 2))) + sprintf(*t, "%s:%s", q, p); + return SOAP_OK; + } + } + if (np->ns) + { if ((*t = (char*)soap_malloc(soap, strlen(p) + strlen(np->ns) + 4))) + sprintf(*t, "\"%s\":%s", np->ns, p); + return SOAP_OK; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Namespace prefix of '%s' not defined (index=%d, URI=%s)\n", s, np->index, np->ns?np->ns:"")); + return soap->error = SOAP_NAMESPACE; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Namespace prefix of '%s' not defined, assuming empty namespace\n", s)); + if ((*t = (char*)soap_malloc(soap, strlen(p) + 4))) + sprintf(*t, "\"\":%s", p); + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_QName2s(struct soap *soap, const char *s) +{ struct Namespace *p; + char *t; + int n; + if (!s || *s != '"') + return s; + s++; + if ((p = soap->local_namespaces)) + { for (; p->id; p++) + { if (p->ns) + if (!soap_tag_cmp(s, p->ns)) + break; + if (p->in) + if (!soap_tag_cmp(s, p->in)) + break; + } + if (p && p->id) + { s = strchr(s, '"'); + if (s) + { t = (char*)soap_malloc(soap, strlen(p->id) + strlen(s)); + strcpy(t, p->id); + strcat(t, s + 1); + return t; + } + } + } + t = (char*)strchr(s, '"'); + if (t) + n = t - s; + else + n = 0; + t = soap_strdup(soap, s); + t[n] = '\0'; + sprintf(soap->tmpbuf, "xmlns:_%lu", soap->idnum++); + soap_set_attr(soap, soap->tmpbuf, t); + s = strchr(s, '"'); + if (s) + { t = (char*)soap_malloc(soap, strlen(soap->tmpbuf) + strlen(s) - 6); + strcpy(t, soap->tmpbuf + 6); + strcat(t, s + 1); + } + return t; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outstring(struct soap *soap, const char *tag, int id, char *const*p, const char *type, int n) +{ id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n); + if (id < 0 + || soap_element_begin_out(soap, tag, id, type) + || soap_string_out(soap, *p, 0) + || soap_element_end_out(soap, tag)) + return soap->error; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char ** +SOAP_FMAC2 +soap_instring(struct soap *soap, const char *tag, char **p, const char *type, int t, int flag, long minlen, long maxlen) +{ if (soap_element_begin_in(soap, tag, 1)) + { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG) + return NULL; + soap->error = SOAP_OK; + } + if (!p) + if (!(p = (char**)soap_malloc(soap, sizeof(char*)))) + return NULL; + if (soap->body) + { *p = soap_string_in(soap, flag, minlen, maxlen); + if (!*p || !(char*)soap_id_enter(soap, soap->id, *p, t, sizeof(char*), 0, NULL, NULL, NULL)) + return NULL; + } + else + *p = NULL; + p = (char**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(char**), 0); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outwstring(struct soap *soap, const char *tag, int id, wchar_t *const*p, const char *type, int n) +{ id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n); + if (id < 0 + || soap_element_begin_out(soap, tag, id, type) + || soap_wstring_out(soap, *p, 0) + || soap_element_end_out(soap, tag)) + return soap->error; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +wchar_t ** +SOAP_FMAC2 +soap_inwstring(struct soap *soap, const char *tag, wchar_t **p, const char *type, int t, long minlen, long maxlen) +{ if (soap_element_begin_in(soap, tag, 1)) + { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG) + return NULL; + soap->error = SOAP_OK; + } + if (!p) + if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*)))) + return NULL; + if (soap->body) + { *p = soap_wstring_in(soap, 1, minlen, maxlen); + if (!*p || !(wchar_t*)soap_id_enter(soap, soap->id, *p, t, sizeof(wchar_t*), 0, NULL, NULL, NULL)) + return NULL; + } + else + *p = NULL; + p = (wchar_t**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(wchar_t**), 0); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static time_t +soap_timegm(struct tm *T) +{ +#if defined(HAVE_TIMEGM) + return timegm(T); +#elif defined(HAVE_GETTIMEOFDAY) + struct timezone t; + struct timeval tv; + memset((void*)&t, 0, sizeof(t)); + gettimeofday(&tv, &t); + T->tm_min -= t.tz_minuteswest - (t.tz_dsttime != 0)*60; + T->tm_isdst = 0; + return mktime(T); +/* WR[ */ + /* The following define was added for VxWorks*/ +#elif defined(HAVE_MKTIME) + /* FOR VXWORKS: + vxWorks does not seem to have any variable representation of time zones, but + timezone information can be set in INSTALL_DIR/target/h/private/timeP.h header + file, by setting the ZONEBUFFER define. The ZONEBUFFER define follows this + format: + name_of_zone:<(unused)>:time_in_minutes_from_UTC:daylight_start:daylight_end + To calculate local time, the value of time_in_minutes_from_UTC is subtracted + from UTC; time_in_minutes_from_UTC must be positive. Daylight information is + expressed as mmddhh (month-day-hour), for example: + UTC::0:040102:100102 + */ + return mktime(T); +/* ]WR */ +#elif defined(HAVE_FTIME) + struct timeb t; + memset((void*)&t, 0, sizeof(t)); + t.timezone = 0; + t.dstflag = -1; + ftime(&t); + T->tm_min -= t.timezone - (t.dstflag != 0)*60; + T->tm_isdst = 0; + return mktime(T); +#else +#warning "time_t (de)serialization is not MT safe on this platform" + time_t t; + char *tz = getenv("TZ"); + putenv("TZ=UTC"); + tzset(); + t = mktime(T); + if (tz) + { char tmp[16]; + strcpy(tmp, "TZ="); + strncat(tmp, tz, 12); + tmp[15] = '\0'; + putenv(tmp); + } + else + putenv("TZ="); + tzset(); + return t; +#endif +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_dateTime2s(struct soap *soap, time_t n) +{ struct tm T; + struct tm *pT = &T; +#if defined(HAVE_GMTIME_R) + if (gmtime_r(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); +/* WR[ */ + /* The following defines were added for VxWorks*/ +#elif defined(HAVE_PGMTIME_R) + if (gmtime_r(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); +#elif defined(HAVE_PGMTIME) + if (gmtime(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); +/* ]WR */ +#elif defined(HAVE_GMTIME) + if ((pT = gmtime(&n))) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); +#elif defined(HAVE_GETTIMEOFDAY) + struct timezone tz; + memset((void*)&tz, 0, sizeof(tz)); +#if defined(HAVE_LOCALTIME_R) + if (localtime_r(&n, pT)) + { struct timeval tv; + gettimeofday(&tv, &tz); + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(tz.tz_dsttime!=0), abs(tz.tz_minuteswest)%60); + } +#else + if ((pT = localtime(&n))) + { struct timeval tv; + gettimeofday(&tv, &tz); + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(tz.tz_dsttime!=0), abs(tz.tz_minuteswest)%60); + } +#endif +#elif defined(HAVE_FTIME) + struct timeb t; + memset((void*)&t, 0, sizeof(t)); +#if defined(HAVE_LOCALTIME_R) + if (localtime_r(&n, pT)) + { ftime(&t); + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(t.dstflag!=0), abs(t.timezone)%60); + } +/* WR[ */ + /* The following defines were added for VxWorks*/ +#elif defined(HAVE_PLOCALTIME_R) + if (localtime_r(&n, pT)) + { strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf+strlen(soap->tmpbuf), "%+03d:%02d", t.timezone/60, abs(t.timezone)%60); + } +/* ]WR */ +#else + if ((pT = localtime(&n))) + { ftime(&t); + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(t.dstflag!=0), abs(t.timezone)%60); + } +#endif +#elif defined(HAVE_LOCALTIME_R) + if (localtime_r(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); +/* WR[ */ + /* The following defines were added for VxWorks*/ +#elif defined(HAVE_PLOCALTIME_R) + if (localtime_r(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); +/* ]WR */ +#else + if ((pT = localtime(&n))) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); +#endif + else + strcpy(soap->tmpbuf, "1969-12-31T23:59:59Z"); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outdateTime(struct soap *soap, const char *tag, int id, const time_t *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_dateTime2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2dateTime(struct soap *soap, const char *s, time_t *p) +{ if (s) + { struct tm T; + char zone[16]; + memset((void*)&T, 0, sizeof(T)); + zone[sizeof(zone)-1] = '\0'; + sscanf(s, "%d-%d-%dT%d:%d:%d%15s", &T.tm_year, &T.tm_mon, &T.tm_mday, &T.tm_hour, &T.tm_min, &T.tm_sec, zone); + if (T.tm_year == 1) + T.tm_year = 70; + else + T.tm_year -= 1900; + T.tm_mon--; + if (*zone) + { if (*zone == '.') + { for (s = zone + 1; *s; s++) + if (*s < '0' || *s > '9') + break; + } + else + s = zone; + if (*s != 'Z') + { int h = 0, m = 0; + sscanf(s, "%d:%d", &h, &m); + T.tm_hour -= h; + if (h >= 0) + T.tm_min -= m; + else + T.tm_min += m; + } + *p = soap_timegm(&T); + } + else + *p = mktime(&T); /* no time zone: suppose it is localtime? */ + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +time_t * +SOAP_FMAC2 +soap_indateTime(struct soap *soap, const char *tag, time_t *p, const char * type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":dateTime")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } + p = (time_t*)soap_id_enter(soap, soap->id, p, t, sizeof(time_t), 0, NULL, NULL, NULL); + if (p) + { if (soap_s2dateTime(soap, soap_value(soap), p)) + return NULL; + } + p = (time_t*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(time_t), 0, NULL); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outliteral(struct soap *soap, const char *tag, char *const*p) +{ int i; + const char *t = NULL; + if (tag && *tag != '-') + { if ((t = strchr(tag, ':'))) + { strncpy(soap->tmpbuf, tag, t-tag); + soap->tmpbuf[t-tag] = '\0'; + for (i = 0; soap->local_namespaces[i].id; i++) + if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id)) + break; + t++; + sprintf(soap->tmpbuf, "<%s xmlns=\"%s\">", t, soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS); + } + else + { t = tag; + sprintf(soap->tmpbuf, "<%s>", tag); + } + if (soap_send(soap, soap->tmpbuf)) + return soap->error; + } + if (p && *p) + { if (soap_send(soap, *p)) + return soap->error; + } + if (t) + { sprintf(soap->tmpbuf, "", t); + return soap_send(soap, soap->tmpbuf); + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char ** +SOAP_FMAC2 +soap_inliteral(struct soap *soap, const char *tag, char **p) +{ if (soap_element_begin_in(soap, tag, 1)) + { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT) + return NULL; + soap->error = SOAP_OK; + } + if (!p) + if (!(p = (char**)soap_malloc(soap, sizeof(char*)))) + return NULL; + if (soap->null) + *p = NULL; + else + *p = soap_string_in(soap, 0, -1, -1); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outwliteral(struct soap *soap, const char *tag, wchar_t *const*p) +{ int i; + const char *t = NULL; + wchar_t c; + const wchar_t *s; + if (tag && *tag != '-') + { if (tag && (t = strchr(tag, ':'))) + { strncpy(soap->tmpbuf, tag, t-tag); + soap->tmpbuf[t-tag] = '\0'; + for (i = 0; soap->local_namespaces[i].id; i++) + if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id)) + break; + t++; + sprintf(soap->tmpbuf, "<%s xmlns=\"%s\">", t, soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS); + } + else + { t = tag; + sprintf(soap->tmpbuf, "<%s>", tag); + } + if (soap_send(soap, soap->tmpbuf)) + return soap->error; + } + if (p) + { s = *p; + while ((c = *s++)) + if (soap_pututf8(soap, (unsigned char)c)) + return soap->error; + } + if (t) + { sprintf(soap->tmpbuf, "", t); + return soap_send(soap, soap->tmpbuf); + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +wchar_t ** +SOAP_FMAC2 +soap_inwliteral(struct soap *soap, const char *tag, wchar_t **p) +{ if (soap_element_begin_in(soap, tag, 1)) + { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT) + return NULL; + soap->error = SOAP_OK; + } + if (!p) + if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*)))) + return NULL; + if (soap->null) + *p = NULL; + else + *p = soap_wstring_in(soap, 0, -1, -1); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char * +SOAP_FMAC2 +soap_value(struct soap *soap) +{ size_t i; + soap_wchar c = 0; + char *s = soap->tmpbuf; + if (!soap->body) + return SOAP_STR_EOS; + for (i = 0; i < sizeof(soap->tmpbuf) - 1; i++) + { c = soap_get(soap); + if (c == SOAP_TT || (int)c == EOF || soap_blank(c)) + break; + *s++ = (char)c; + } + if ((int)c == EOF || c == SOAP_TT) + soap_unget(soap, c); + *s = '\0'; + return soap->tmpbuf; /* return non-null pointer */ +} +#endif + +/******************************************************************************/ +#if !defined(WITH_LEANER) || !defined(WITH_NOHTTP) +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getline(struct soap *soap, char *s, int len) +{ int i = len; + soap_wchar c = 0; + for (;;) + { while (--i > 0) + { c = soap_getchar(soap); + if (c == '\r' || c == '\n') + break; + if ((int)c == EOF) + return soap->error = SOAP_EOF; + *s++ = (char)c; + } + if (c != '\n') + c = soap_getchar(soap); /* got \r, now get \n */ + if (c == '\n') + { *s = '\0'; + if (i+1 == len) /* empty line: end of HTTP/MIME header */ + break; + c = soap_unget(soap, soap_getchar(soap)); + if (c != ' ' && c != '\t') /* HTTP line continuation? */ + break; + } + else if ((int)c == EOF) + return soap->error = SOAP_EOF; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static size_t +soap_count_attachments(struct soap *soap) +{ +#ifndef WITH_LEANER + register struct soap_multipart *content; + register size_t count = soap->count; + if (soap->mode & SOAP_ENC_DIME) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of DIME attachments\n")); + for (content = soap->dime.first; content; content = content->next) + { count += 12 + ((content->size+3)&(~3)); + if (content->id) + count += ((strlen(content->id)+3)&(~3)); + if (content->type) + count += ((strlen(content->type)+3)&(~3)); + if (content->options) + count += ((((unsigned char)content->options[2] << 8) | ((unsigned char)content->options[3]))+7)&(~3); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of DIME attachment %lu bytes\n", (unsigned long)content->size)); + } + } + if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary) + { register size_t n = strlen(soap->mime.boundary); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of MIME attachments\n")); + for (content = soap->mime.first; content; content = content->next) + { register const char *s; + /* count \r\n--boundary\r\n */ + count += 6 + n; + /* count Content-Type: ...\r\n */ + if (content->type) + count += 16 + strlen(content->type); + s = soap_str_code(mime_codes, content->encoding); + /* count Content-Transfer-Encoding: ...\r\n */ + if (s) + count += 29 + strlen(s); + /* count Content-ID: ...\r\n */ + if (content->id) + count += 14 + strlen(content->id); + /* count Content-Location: ...\r\n */ + if (content->location) + count += 20 + strlen(content->location); + /* count Content-Description: ...\r\n */ + if (content->description) + count += 23 + strlen(content->location); + /* count \r\n...content */ + count += 2 + content->size; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of MIME attachment %lu bytes\n", (unsigned long)content->size)); + } + /* count \r\n--boundary--\r\n */ + count += 8 + n; + } + return count; +#else + return soap->count; +#endif +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static int +soap_putdimefield(struct soap *soap, const char *s, size_t n) +{ if (soap_send_raw(soap, s, n)) + return soap->error; + return soap_send_raw(soap, SOAP_STR_PADDING, -(long)n&3); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_dime_option(struct soap *soap, unsigned short optype, const char *option) +{ size_t n; + char *s = NULL; + if (option) + { n = strlen(option); + s = (char*)soap_malloc(soap, n + 5); + if (s) + { s[0] = optype >> 8; + s[1] = optype & 0xFF; + s[2] = n >> 8; + s[3] = n & 0xFF; + strcpy(s + 4, option); + } + } + return s; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putdimehdr(struct soap *soap) +{ unsigned char tmp[12]; + size_t optlen = 0, idlen = 0, typelen = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Put DIME header id='%s'\n", soap->dime.id?soap->dime.id:"")); + if (soap->dime.options) + optlen = (((unsigned char)soap->dime.options[2] << 8) | ((unsigned char)soap->dime.options[3])) + 4; + if (soap->dime.id) + idlen = strlen(soap->dime.id); + if (soap->dime.type) + typelen = strlen(soap->dime.type); + tmp[0] = SOAP_DIME_VERSION | (soap->dime.flags & 0x7); + tmp[1] = soap->dime.flags & 0xF0; + tmp[2] = optlen >> 8; + tmp[3] = optlen & 0xFF; + tmp[4] = idlen >> 8; + tmp[5] = idlen & 0xFF; + tmp[6] = typelen >> 8; + tmp[7] = typelen & 0xFF; + tmp[8] = soap->dime.size >> 24; + tmp[9] = (soap->dime.size >> 16) & 0xFF; + tmp[10] = (soap->dime.size >> 8) & 0xFF; + tmp[11] = soap->dime.size & 0xFF; + if (soap_send_raw(soap, (char*)tmp, 12) + || soap_putdimefield(soap, soap->dime.options, optlen) + || soap_putdimefield(soap, soap->dime.id, idlen) + || soap_putdimefield(soap, soap->dime.type, typelen)) + return soap->error; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putdime(struct soap *soap) +{ struct soap_multipart *content; + if (!(soap->mode & SOAP_ENC_DIME)) + return SOAP_OK; + for (content = soap->dime.first; content; content = content->next) + { void *handle; + soap->dime.size = content->size; + soap->dime.id = content->id; + soap->dime.type = content->type; + soap->dime.options = content->options; + soap->dime.flags = SOAP_DIME_VERSION | SOAP_DIME_MEDIA; + if (soap->fdimereadopen && ((handle = soap->fdimereadopen(soap, (void*)content->ptr, content->id, content->type, content->options)) || soap->error)) + { size_t size = content->size; + if (!handle) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadopen failed\n")); + return soap->error; + } + if (!content->size && ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE)) + { size_t chunksize = sizeof(soap->tmpbuf); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming DIME\n")); + do + { size = soap->fdimeread(soap, handle, soap->tmpbuf, chunksize); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread returned %lu bytes\n", (unsigned long)size)); + if (size < chunksize) + { soap->dime.flags &= ~SOAP_DIME_CF; + if (!content->next) + soap->dime.flags |= SOAP_DIME_ME; + } + else + soap->dime.flags |= SOAP_DIME_CF; + soap->dime.size = size; + if (soap_putdimehdr(soap) + || soap_putdimefield(soap, soap->tmpbuf, size)) + break; + if (soap->dime.id) + { soap->dime.flags &= ~(SOAP_DIME_MB | SOAP_DIME_MEDIA); + soap->dime.id = NULL; + soap->dime.type = NULL; + soap->dime.options = NULL; + } + } while (size >= chunksize); + } + else + { if (!content->next) + soap->dime.flags |= SOAP_DIME_ME; + if (soap_putdimehdr(soap)) + return soap->error; + do + { size_t bufsize; + if (size < sizeof(soap->tmpbuf)) + bufsize = size; + else + bufsize = sizeof(soap->tmpbuf); + if (!(bufsize = soap->fdimeread(soap, handle, soap->tmpbuf, bufsize))) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)soap->dime.size)); + soap->error = SOAP_EOF; + break; + } + if (soap_send_raw(soap, soap->tmpbuf, bufsize)) + break; + size -= bufsize; + } while (size); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n")); + soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3); + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n")); + if (soap->fdimereadclose) + soap->fdimereadclose(soap, handle); + } + else + { if (!content->next) + soap->dime.flags |= SOAP_DIME_ME; + if (soap_putdimehdr(soap) + || soap_putdimefield(soap, (char*)content->ptr, content->size)) + return soap->error; + } + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static char * +soap_getdimefield(struct soap *soap, size_t n) +{ register soap_wchar c; + register int i; + register char *s; + char *p = NULL; + if (n) + { p = (char*)soap_malloc(soap, n + 1); + if (p) + { s = p; + for (i = n; i > 0; i--) + { if ((int)(c = soap_get1(soap)) == EOF) + { soap->error = SOAP_EOF; + return NULL; + } + *s++ = (char)c; + } + *s = '\0'; + if ((soap->error = soap_move(soap, -(long)n&3))) + return NULL; + } + else + soap->error = SOAP_EOM; + } + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getdimehdr(struct soap *soap) +{ register soap_wchar c; + register char *s; + register int i; + unsigned char tmp[12]; + size_t optlen, idlen, typelen; + if (!(soap->mode & SOAP_ENC_DIME)) + return soap->error = SOAP_DIME_END; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME header\n")); + if (soap->dime.buflen || soap->dime.chunksize) + { if (soap_move(soap, (long)(soap->dime.size - soap_tell(soap)))) + return soap->error = SOAP_EOF; + soap_unget(soap, soap_getchar(soap)); /* skip padding and get hdr */ + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... From chunked\n")); + return SOAP_OK; + } + s = (char*)tmp; + for (i = 12; i > 0; i--) + { if ((int)(c = soap_getchar(soap)) == EOF) + return soap->error = SOAP_EOF; + *s++ = (char)c; + } + if ((tmp[0] & 0xF8) != SOAP_DIME_VERSION) + return soap->error = SOAP_DIME_MISMATCH; + soap->dime.flags = (tmp[0] & 0x7) | (tmp[1] & 0xF0); + optlen = (tmp[2] << 8) | tmp[3]; + idlen = (tmp[4] << 8) | tmp[5]; + typelen = (tmp[6] << 8) | tmp[7]; + soap->dime.size = (tmp[8] << 24) | (tmp[9] << 16) | (tmp[10] << 8) | tmp[11]; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME size=%lu flags=0x%X\n", (unsigned long)soap->dime.size, soap->dime.flags)); + if (!(soap->dime.options = soap_getdimefield(soap, optlen)) && soap->error) + return soap->error; + if (!(soap->dime.id = soap_getdimefield(soap, idlen)) && soap->error) + return soap->error; + if (!(soap->dime.type = soap_getdimefield(soap, typelen)) && soap->error) + return soap->error; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME id=%s, type=%s, options=%s\n", soap->dime.id?soap->dime.id:"", soap->dime.type?soap->dime.type:"", soap->dime.options?soap->dime.options+4:"")); + if (soap->dime.flags & SOAP_DIME_ME) + soap->mode &= ~SOAP_ENC_DIME; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getdime(struct soap *soap) +{ struct soap_multipart *content; + if (soap_getdimehdr(soap)) + return soap->error; + if (soap->fdimewriteopen && ((soap->dime.ptr = (char*)soap->fdimewriteopen(soap, soap->dime.id, soap->dime.type, soap->dime.options)) || soap->error)) + { const char *id, *type, *options; + size_t size, n; + if (!soap->dime.ptr) + return soap->error; + id = soap->dime.id; + type = soap->dime.type; + options = soap->dime.options; + for (;;) + { size = soap->dime.size; + for (;;) + { n = soap->buflen - soap->bufidx; + if (size < n) + n = size; + if ((soap->error = soap->fdimewrite(soap, (void*)soap->dime.ptr, soap->buf + soap->bufidx, n))) + break; + size -= n; + if (!size) + { soap->bufidx += n; + break; + } + if (soap_recv(soap)) + { soap->error = SOAP_EOF; + goto end; + } + } + if (soap_move(soap, -(long)soap->dime.size&3)) + { soap->error = SOAP_EOF; + break; + } + if (!(soap->dime.flags & SOAP_DIME_CF)) + break; + if (soap_getdimehdr(soap)) + break; + } +end: + if (soap->fdimewriteclose) + soap->fdimewriteclose(soap, (void*)soap->dime.ptr); + soap->dime.size = 0; + soap->dime.id = id; + soap->dime.type = type; + soap->dime.options = options; + } + else if (soap->dime.flags & SOAP_DIME_CF) + { const char *id, *type, *options; + register soap_wchar c; + register char *s; + register int i; + id = soap->dime.id; + type = soap->dime.type; + options = soap->dime.options; + if (soap_new_block(soap)) + return SOAP_EOM; + for (;;) + { s = (char*)soap_push_block(soap, soap->dime.size); + if (!s) + return soap->error = SOAP_EOM; + for (i = soap->dime.size; i > 0; i--) + { if ((int)(c = soap_get1(soap)) == EOF) + return soap->error = SOAP_EOF; + *s++ = (char)c; + } + if (soap_move(soap, -(long)soap->dime.size&3)) + return soap->error = SOAP_EOF; + if (!(soap->dime.flags & SOAP_DIME_CF)) + break; + if (soap_getdimehdr(soap)) + return soap->error; + } + soap->dime.size = soap->blist->size++; /* allocate one more for '\0' */ + if (!(soap->dime.ptr = soap_save_block(soap, NULL, 0))) + return soap->error; + soap->dime.ptr[soap->dime.size] = '\0'; /* force 0-terminated */ + soap->dime.id = id; + soap->dime.type = type; + soap->dime.options = options; + } + else + soap->dime.ptr = soap_getdimefield(soap, soap->dime.size); + content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, soap->dime.ptr, soap->dime.size); + if (!content) + return soap->error = SOAP_EOM; + content->id = soap->dime.id; + content->type = soap->dime.type; + content->options = soap->dime.options; + return soap->error; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getmimehdr(struct soap *soap) +{ struct soap_multipart *content; + do + { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) + return soap->error; + } + while (!*soap->msgbuf); + if (soap->msgbuf[0] == '-' && soap->msgbuf[1] == '-') + { char *s = soap->msgbuf + strlen(soap->msgbuf) - 1; + /* remove white space */ + while (soap_blank(*s)) + s--; + s[1] = '\0'; + if (soap->mime.boundary) + { if (strcmp(soap->msgbuf + 2, soap->mime.boundary)) + return soap->error = SOAP_MIME_ERROR; + } + else + soap->mime.boundary = soap_strdup(soap, soap->msgbuf + 2); + if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) + return soap->error; + } + if (soap_set_mime_attachment(soap, NULL, 0, SOAP_MIME_NONE, NULL, NULL, NULL, NULL)) + return soap->error = SOAP_EOM; + content = soap->mime.last; + for (;;) + { register char *key = soap->msgbuf; + register char *val; + if (!*key) + break; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "MIME header: %s\n", key)); + val = strchr(soap->msgbuf, ':'); + if (val) + { *val = '\0'; + do val++; + while (*val && *val <= 32); + if (!soap_tag_cmp(key, "Content-ID")) + content->id = soap_strdup(soap, val); + else if (!soap_tag_cmp(key, "Content-Location")) + content->location = soap_strdup(soap, val); + else if (!soap_tag_cmp(key, "Content-Type")) + content->type = soap_strdup(soap, val); + else if (!soap_tag_cmp(key, "Content-Description")) + content->description = soap_strdup(soap, val); + else if (!soap_tag_cmp(key, "Content-Transfer-Encoding")) + content->encoding = (enum soap_mime_encoding)soap_int_code(mime_codes, val, (long)SOAP_MIME_NONE); + } + if (soap_getline(soap, key, sizeof(soap->msgbuf))) + return soap->error; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getmime(struct soap *soap) +{ register soap_wchar c; + if (!soap->mime.last) + return SOAP_OK; + for (;;) + { register size_t i, m = 0; + register char *s, *t = NULL; + struct soap_multipart *content = soap->mime.last; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Parsing MIME content id=%s type=%s\n", content->id?content->id:"", content->type?content->type:"")); + if (soap_new_block(soap)) + return soap->error = SOAP_EOM; + for (;;) + { if (!(s = (char*)soap_push_block(soap, SOAP_BLKLEN))) + return soap->error = SOAP_EOM; + for (i = 0; i < SOAP_BLKLEN; i++) + { if (m > 0) + { *s++ = *t++; + m--; + } + else + { c = soap_get1(soap); + if ((int)c == EOF) + return soap->error = SOAP_EOF; + if (c == '\r') + { t = soap->tmpbuf; + memset(t, 0, sizeof(soap->tmpbuf)); + strcpy(t, "\n--"); + strncat(t, soap->mime.boundary, sizeof(soap->tmpbuf)-4); + do c = soap_getchar(soap); + while (c == *t++); + if ((int)c == EOF) + return soap->error = SOAP_EOF; + if (!*--t) + goto end; + *t = (char)c; + m = t - soap->tmpbuf + 1; + t = soap->tmpbuf; + c = '\r'; + } + *s++ = (char)c; + } + } + } +end: + *s = '\0'; /* force 0-terminated */ + content->size = soap_size_block(soap, i+1)-1; + content->ptr = soap_save_block(soap, NULL, 0); + if (c == '-' && soap_getchar(soap) == '-') + break; + while (c != '\r' && (int)c != EOF && soap_blank(c)) + c = soap_getchar(soap); + if (c != '\r' || soap_getchar(soap) != '\n') + return soap->error = SOAP_MIME_ERROR; + if (soap_getmimehdr(soap)) + return soap->error; + } + do c = soap_getchar(soap); + while ((int)c != EOF && c != '\r'); + if ((int)c == EOF) + return soap->error = SOAP_EOF; + if (soap_getchar(soap) != '\n') + return soap->error = SOAP_MIME_ERROR; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putmimehdr(struct soap *soap, struct soap_multipart *content) +{ const char *s; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "MIME attachment type=%s\n", content->type?content->type:"")); + if (soap_send3(soap, "\r\n--", soap->mime.boundary, "\r\n")) + return soap->error; + if (content->type && soap_send3(soap, "Content-Type: ", content->type, "\r\n")) + return soap->error; + s = soap_str_code(mime_codes, content->encoding); + if (s && soap_send3(soap, "Content-Transfer-Encoding: ", s, "\r\n")) + return soap->error; + if (content->id && soap_send3(soap, "Content-ID: ", content->id, "\r\n")) + return soap->error; + if (content->location && soap_send3(soap, "Content-Location: ", content->location, "\r\n")) + return soap->error; + if (content->description && soap_send3(soap, "Content-Description: ", content->description, "\r\n")) + return soap->error; + return soap_send_raw(soap, "\r\n", 2); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putmime(struct soap *soap) +{ struct soap_multipart *content; + if (!(soap->mode & SOAP_ENC_MIME) || !soap->mime.boundary) + return SOAP_OK; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending MIME attachments\n")); + for (content = soap->mime.first; content; content = content->next) + if (soap_putmimehdr(soap, content) + || soap_send_raw(soap, content->ptr, content->size)) + return soap->error; + return soap_send3(soap, "\r\n--", soap->mime.boundary, "--\r\n"); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_dime(struct soap *soap) +{ soap->omode |= SOAP_ENC_DIME; + soap->dime.first = NULL; + soap->dime.last = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_mime(struct soap *soap, const char *boundary, const char *start) +{ soap->omode |= SOAP_ENC_MIME; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = soap_strdup(soap, boundary); + soap->mime.start = soap_strdup(soap, start); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_clr_dime(struct soap *soap) +{ soap->omode &= ~SOAP_ENC_DIME; + soap->dime.first = NULL; + soap->dime.last = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_clr_mime(struct soap *soap) +{ soap->omode &= ~SOAP_ENC_MIME; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = NULL; + soap->mime.start = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static struct soap_multipart* +soap_new_multipart(struct soap *soap, struct soap_multipart **first, struct soap_multipart **last, char *ptr, size_t size) +{ struct soap_multipart *content; + content = (struct soap_multipart*)soap_malloc(soap, sizeof(struct soap_multipart)); + if (content) + { content->next = NULL; + content->ptr = ptr; + content->size = size; + content->id = NULL; + content->type = NULL; + content->options = NULL; + content->encoding = SOAP_MIME_NONE; + content->location = NULL; + content->description = NULL; + if (!*first) + *first = content; + if (*last) + (*last)->next = content; + *last = content; + } + return content; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_dime_attachment(struct soap *soap, char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option) +{ struct soap_multipart *content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, ptr, size); + if (!content) + return SOAP_EOM; + content->id = soap_strdup(soap, id); + content->type = soap_strdup(soap, type); + content->options = soap_dime_option(soap, optype, option); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_mime_attachment(struct soap *soap, char *ptr, size_t size, enum soap_mime_encoding encoding, const char *type, const char *id, const char *location, const char *description) +{ struct soap_multipart *content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, ptr, size); + if (!content) + return SOAP_EOM; + content->id = soap_strdup(soap, id); + content->type = soap_strdup(soap, type); + content->encoding = encoding; + content->location = soap_strdup(soap, location); + content->description = soap_strdup(soap, description); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +struct soap_multipart* +SOAP_FMAC2 +soap_next_multipart(struct soap_multipart *content) +{ if (content) + return content->next; + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static void +soap_select_mime_boundary(struct soap *soap) +{ while (!soap->mime.boundary || soap_valid_mime_boundary(soap)) + { register char *s = soap->mime.boundary; + register size_t n = 0; + if (s) + n = strlen(s); + if (n < 16) + { n = 72; + s = soap->mime.boundary = (char*)soap_malloc(soap, n + 1); + if (!s) + return; + } + strcpy(s, "<>"); + s += 2; + n -= 4; + while (n) + { *s++ = soap_base64o[rand()&0x3F]; + n--; + } + strcpy(s, "<>"); + } + if (!soap->mime.start) + soap->mime.start = ""; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static int +soap_valid_mime_boundary(struct soap *soap) +{ register struct soap_multipart *content; + register size_t k = strlen(soap->mime.boundary); + for (content = soap->mime.first; content; content = content->next) + { if (content->ptr && content->size >= k) + { register const char *p = (const char*)content->ptr; + register size_t i; + for (i = 0; i < content->size - k; i++, p++) + if (!strncmp(p, soap->mime.boundary, k)) + return SOAP_ERR; + } + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ + +#ifdef WITH_COOKIES +/******************************************************************************/ +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_encode_cookie(const char *s, char *t, size_t len) +{ register int c; + register size_t n = len; + while ((c = *s++) && --n > 0) + { if (c > ' ' && c < 128 && !strchr("()<>@,;:\\\"/[]?={}", c)) + *t++ = c; + else if (n > 2) + { *t++ = '%'; + *t++ = (c >> 4) + (c > 159 ? '7' : '0'); + c &= 0xF; + *t++ = c + (c > 9 ? '7' : '0'); + n -= 2; + } + else + break; + } + *t = '\0'; + return len - n; +} + +/******************************************************************************/ +SOAP_FMAC1 +struct soap_cookie* +SOAP_FMAC2 +soap_cookie(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + size_t n; + if (!domain) + domain = soap->cookie_domain; + if (!path) + path = soap->cookie_path; + if (*path == '/') + path++; + n = strlen(path); + for (p = soap->cookies; p; p = p->next) + if (!strcmp(p->name, name) + && domain + && p->domain + && !strcmp(p->domain, domain) + && !strncmp(p->path, path, n)) + break; + return p; +} + +/******************************************************************************/ +SOAP_FMAC1 +struct soap_cookie* +SOAP_FMAC2 +soap_set_cookie(struct soap *soap, const char *name, const char *value, const char *domain, const char *path) +{ struct soap_cookie **p, *q; + int n; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set cookie: %s=%s domain=%s path=%s\n", name, value?value:"", domain?domain:"", path?path:"")); + if (!domain) + domain = soap->cookie_domain; + if (!path) + path = soap->cookie_path; + if (!path) + { soap_set_receiver_error(soap, "Cookie path not set", NULL, SOAP_HTTP_ERROR); + return NULL; + } + if (*path == '/') + path++; + q = soap_cookie(soap, name, domain, path); + if (!q) + { if ((q = (struct soap_cookie*)SOAP_MALLOC(sizeof(struct soap_cookie)))) + { if ((q->name = (char*)SOAP_MALLOC(strlen(name)+1))) + strcpy(q->name, name); + q->value = NULL; + q->domain = NULL; + q->path = NULL; + q->expire = -1; + q->version = 0; + q->secure = 0; + q->env = 0; + q->modified = 0; + for (p = &soap->cookies, n = soap->cookie_max; *p && n; p = &(*p)->next, n--) + if (!strcmp((*p)->name, name) && (*p)->path && strcmp((*p)->path, path) < 0) + break; + if (n) + { q->next = *p; + *p = q; + } + else + { SOAP_FREE(q->name); + SOAP_FREE(q); + q = NULL; + } + } + } + else + q->modified = 1; + if (q) + { if (q->value) + { SOAP_FREE(q->value); + q->value = NULL; + } + if (q->domain) + { SOAP_FREE(q->domain); + q->domain = NULL; + } + if (q->path) + { SOAP_FREE(q->path); + q->path = NULL; + } + if (value && *value && (q->value = (char*)SOAP_MALLOC(strlen(value)+1))) + strcpy(q->value, value); + if (domain && *domain && (q->domain = (char*)SOAP_MALLOC(strlen(domain)+1))) + strcpy(q->domain, domain); + if (path && *path && (q->path = (char*)SOAP_MALLOC(strlen(path)+1))) + strcpy(q->path, path); + q->session = 1; + } + return q; +} + +/******************************************************************************/ +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_clr_cookie(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie **p, *q; + if (!domain) + domain = soap->cookie_domain; + if (!domain) + { soap_set_receiver_error(soap, "Cookie domain not set", SOAP_STR_EOS, SOAP_HTTP_ERROR); + return; + } + if (!path) + path = soap->cookie_path; + if (!path) + { soap_set_receiver_error(soap, "Cookie path not set", SOAP_STR_EOS, SOAP_HTTP_ERROR); + return; + } + if (*path == '/') + path++; + for (p = &soap->cookies, q = *p; q; q = *p) + if (!strcmp(q->name, name) && !strcmp(q->domain, domain) && !strncmp(q->path, path, strlen(q->path))) + { if (q->value) + SOAP_FREE(q->value); + if (q->domain) + SOAP_FREE(q->domain); + if (q->path) + SOAP_FREE(q->path); + *p = q->next; + SOAP_FREE(q); + } + else + p = &q->next; +} + +/******************************************************************************/ +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + return p->value; + return NULL; +} + +/******************************************************************************/ +SOAP_FMAC1 +long +SOAP_FMAC2 +soap_cookie_expire(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + return p->expire; + return -1; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_cookie_expire(struct soap *soap, const char *name, long expire, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + { p->expire = expire; + p->modified = 1; + return SOAP_OK; + } + return SOAP_ERR; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + { p->session = 1; + p->modified = 1; + return SOAP_OK; + } + return SOAP_ERR; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_clr_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + { p->session = 0; + p->modified = 1; + return SOAP_OK; + } + return SOAP_ERR; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putsetcookies(struct soap *soap) +{ struct soap_cookie *p; + char *s, tmp[4096]; + const char *t; + for (p = soap->cookies; p; p = p->next) + { if (p->modified || !p->env) + { s = tmp; + if (p->name) + s += soap_encode_cookie(p->name, s, tmp-s+4064); + if (p->value && *p->value) + { *s++ = '='; + s += soap_encode_cookie(p->value, s, tmp-s+4064); + } + if (p->domain && (int)strlen(p->domain) < tmp-s+4064) + sprintf(s, ";Domain=\"%s\"", p->domain); + else if (soap->cookie_domain && (int)strlen(soap->cookie_domain) < tmp-s+4064) + sprintf(s, ";Domain=\"%s\"", soap->cookie_domain); + strcat(s, ";Path=\"/"); + if (p->path) + t = p->path; + else + t = soap->cookie_path; + if (t) + { if (*t == '/') + t++; + if ((int)strlen(t) < tmp-s+4064) + strcat(s, t); + } + s += strlen(s); + *s++ = '"'; + if (p->version > 0) + sprintf(s, ";Version=%u", p->version); + if (p->expire >= 0) + sprintf(s, ";Max-Age=%ld", p->expire); + if (p->secure) + strcat(s, ";Secure"); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set-Cookie: %s\n", tmp)); + if (soap->fposthdr(soap, "Set-Cookie", tmp)) + return soap->error; + } + } + return SOAP_OK; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putcookies(struct soap *soap, const char *domain, const char *path, int secure) +{ struct soap_cookie **p, *q; + unsigned int version = 0; + time_t now = time(NULL); + char *s, tmp[4096]; + p = &soap->cookies; + while ((q = *p)) + { if (q->expire && now > q->expire) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie %s expired\n", q->name)); + SOAP_FREE(q->name); + if (q->value) + SOAP_FREE(q->value); + if (q->domain) + SOAP_FREE(q->domain); + if (q->path) + SOAP_FREE(q->path); + *p = q->next; + SOAP_FREE(q); + } + else if ((!q->domain || !strcmp(q->domain, domain)) + && (!q->path || !strncmp(q->path, path, strlen(q->path))) + && (!q->secure || secure)) + { s = tmp; + if (q->version != version) + { sprintf(s, "$Version=%u;", q->version); + version = q->version; + } + if (q->name) + s += soap_encode_cookie(q->name, s, tmp-s+4080); + if (q->value && *q->value) + { *s++ = '='; + s += soap_encode_cookie(q->value, s, tmp-s+4080); + } + if (q->path && (int)strlen(q->path) < tmp-s+4080) + { sprintf(s, ";$Path=\"/%s\"", q->path); + s += strlen(s); + } + if (q->domain && (int)strlen(q->domain) < tmp-s+4080) + sprintf(s, ";$Domain=\"%s\"", q->domain); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie: %s\n", tmp)); + if (soap->fposthdr(soap, "Cookie", tmp)) + return soap->error; + p = &q->next; + } + else + p = &q->next; + } + return SOAP_OK; +} + +/******************************************************************************/ +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_getcookies(struct soap *soap, const char *val) +{ struct soap_cookie *p = NULL, *q; + const char *s; + char *t, tmp[4096]; /* cookie size is up to 4096 bytes [RFC2109] */ + char *domain = NULL; + char *path = NULL; + unsigned int version = 0; + time_t now = time(NULL); + if (!val) + return; + s = val; + while (*s) + { s = soap_decode_key(tmp, sizeof(tmp), s); + if (!soap_tag_cmp(tmp, "$Version")) + { if ((s = soap_decode_val(tmp, sizeof(tmp), s))) + { if (p) + p->version = (int)atol(tmp); + else + version = (int)atol(tmp); + } + } + else if (!soap_tag_cmp(tmp, "$Path")) + { s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { if ((t = (char*)SOAP_MALLOC(strlen(tmp)+1))) + strcpy(t, tmp); + } + else + t = NULL; + if (p) + { if (p->path) + SOAP_FREE(p->path); + p->path = t; + } + else + { if (path) + SOAP_FREE(path); + path = t; + } + } + else if (!soap_tag_cmp(tmp, "$Domain")) + { s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { if ((t = (char*)SOAP_MALLOC(strlen(tmp)+1))) + strcpy(t, tmp); + } + else + t = NULL; + if (p) + { if (p->domain) + SOAP_FREE(p->domain); + p->domain = t; + } + else + { if (domain) + SOAP_FREE(domain); + domain = t; + } + } + else if (p && !soap_tag_cmp(tmp, "Path")) + { if (p->path) + SOAP_FREE(p->path); + s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { if ((p->path = (char*)SOAP_MALLOC(strlen(tmp)+1))) + strcpy(p->path, tmp); + } + else + p->path = NULL; + } + else if (p && !soap_tag_cmp(tmp, "Domain")) + { if (p->domain) + SOAP_FREE(p->domain); + s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { if ((p->domain = (char*)SOAP_MALLOC(strlen(tmp)+1))) + strcpy(p->domain, tmp); + } + else + p->domain = NULL; + } + else if (p && !soap_tag_cmp(tmp, "Version")) + { s = soap_decode_val(tmp, sizeof(tmp), s); + p->version = (unsigned int)atol(tmp); + } + else if (p && !soap_tag_cmp(tmp, "Max-Age")) + { s = soap_decode_val(tmp, sizeof(tmp), s); + p->expire = now + atol(tmp); + } + else if (p && !soap_tag_cmp(tmp, "Expires")) + { struct tm T; + char a[3]; + static const char mns[] = "anebarprayunulugepctovec"; + s = soap_decode_val(tmp, sizeof(tmp), s); + if (strlen(tmp) > 20) + { memset((void*)&T, 0, sizeof(T)); + a[0] = tmp[4]; + a[1] = tmp[5]; + a[2] = '\0'; + T.tm_mday = (int)atol(a); + a[0] = tmp[8]; + a[1] = tmp[9]; + T.tm_mon = (strstr(mns, a) - mns) / 2; + a[0] = tmp[11]; + a[1] = tmp[12]; + T.tm_year = 100 + (int)atol(a); + a[0] = tmp[13]; + a[1] = tmp[14]; + T.tm_hour = (int)atol(a); + a[0] = tmp[16]; + a[1] = tmp[17]; + T.tm_min = (int)atol(a); + a[0] = tmp[19]; + a[1] = tmp[20]; + T.tm_sec = (int)atol(a); + p->expire = soap_timegm(&T); + } + } + else if (p && !soap_tag_cmp(tmp, "Secure")) + p->secure = 1; + else + { if (p) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie %s=%s domain=%s path=%s expire=%ld secure=%d\n", p->name, p->value?p->value:"", p->domain?p->domain:"", p->path?p->path:"", p->expire, p->secure)); + if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path))) + { q->version = p->version; + q->expire = p->expire; + q->secure = p->secure; + q->env = 1; + } + if (p->name) + SOAP_FREE(p->name); + if (p->value) + SOAP_FREE(p->value); + if (p->domain) + SOAP_FREE(p->domain); + if (p->path) + SOAP_FREE(p->path); + SOAP_FREE(p); + } + if ((p = (struct soap_cookie*)SOAP_MALLOC(sizeof(struct soap_cookie)))) + { p->name = (char*)SOAP_MALLOC(strlen(tmp)+1); + strcpy(p->name, tmp); + s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { p->value = (char*)SOAP_MALLOC(strlen(tmp)+1); + strcpy(p->value, tmp); + } + else + p->value = NULL; + p->domain = domain; + p->path = path; + p->expire = 0; + p->secure = 0; + p->version = version; + } + } + } + if (p) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got cookie %s=%s domain=%s path=%s expire=%ld secure=%d\n", p->name, p->value?p->value:"", p->domain?p->domain:"", p->path?p->path:"", p->expire, p->secure)); + if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path))) + { q->version = p->version; + q->expire = p->expire; + q->secure = p->secure; + } + if (p->name) + SOAP_FREE(p->name); + if (p->value) + SOAP_FREE(p->value); + if (p->domain) + SOAP_FREE(p->domain); + if (p->path) + SOAP_FREE(p->path); + SOAP_FREE(p); + } + if (domain) + SOAP_FREE(domain); + if (path) + SOAP_FREE(path); +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getenv_cookies(struct soap *soap) +{ struct soap_cookie *p; + const char *s; + char key[4096], val[4096]; /* cookie size is up to 4096 bytes [RFC2109] */ + if (!(s = getenv("HTTP_COOKIE"))) + return SOAP_ERR; + do + { s = soap_decode_key(key, sizeof(key), s); + s = soap_decode_val(val, sizeof(val), s); + p = soap_set_cookie(soap, key, val, NULL, NULL); + if (p) + p->env = 1; + } while (*s); + return SOAP_OK; +} + +/******************************************************************************/ +SOAP_FMAC1 +struct soap_cookie* +SOAP_FMAC2 +soap_copy_cookies(struct soap *soap) +{ struct soap_cookie *p, **q, *r; + q = &r; + for (p = soap->cookies; p; p = p->next) + { if (!(*q = (struct soap_cookie*)SOAP_MALLOC(sizeof(struct soap_cookie)))) + return r; + **q = *p; + if (p->name) + { if (((*q)->name = (char*)SOAP_MALLOC(strlen(p->name)+1))) + strcpy((*q)->name, p->name); + } + if (p->value) + { if (((*q)->value = (char*)SOAP_MALLOC(strlen(p->value)+1))) + strcpy((*q)->value, p->value); + } + if (p->domain) + { if (((*q)->domain = (char*)SOAP_MALLOC(strlen(p->domain)+1))) + strcpy((*q)->domain, p->domain); + } + if (p->path) + { if (((*q)->path = (char*)SOAP_MALLOC(strlen(p->path)+1))) + strcpy((*q)->path, p->path); + } + q = &(*q)->next; + } + *q = NULL; + return r; +} + +/******************************************************************************/ +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_free_cookies(struct soap *soap) +{ struct soap_cookie *p; + for (p = soap->cookies; p; p = soap->cookies) + { soap->cookies = p->next; + SOAP_FREE(p->name); + if (p->value) + SOAP_FREE(p->value); + if (p->domain) + SOAP_FREE(p->domain); + if (p->path) + SOAP_FREE(p->path); + SOAP_FREE(p); + } +} + +/******************************************************************************/ +#endif /* WITH_COOKIES */ + +/******************************************************************************/ +#ifdef WITH_GZIP +#ifndef PALM_1 +static int +soap_getgziphdr(struct soap *soap) +{ int i; + soap_wchar c, f = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get gzip header\n")); + for (i = 0; i < 9; i++) + { if ((int)(c = soap_get1(soap) == EOF)) + return soap->error = SOAP_EOF; + if (i == 2) + f = c; + } + if (f & 0x04) /* FEXTRA */ + { for (i = soap_get1(soap) | (soap_get1(soap) << 8); i; i--) + if ((int)soap_get1(soap) == EOF) + return soap->error = SOAP_EOF; + } + if (f & 0x08) /* FNAME */ + do + c = soap_get1(soap); + while (c && (int)c != EOF); + if ((int)c != EOF && (f & 0x10)) /* FCOMMENT */ + do + c = soap_get1(soap); + while (c && (int)f != EOF); + if ((int)c != EOF && (f & 0x01)) /* FHCRC */ + { if ((int)(c = soap_get1(soap)) != EOF) + c = soap_get1(soap); + } + if ((int)c == EOF) + return soap->error = SOAP_EOF; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_begin_recv(struct soap *soap) +{ soap_wchar c; + soap->error = SOAP_OK; + soap_free(soap); + soap_set_local_namespaces(soap); + soap->version = 0; /* don't assume we're parsing SOAP content by default */ +#ifndef WITH_NOIDREF + soap_free_iht(soap); +#endif + if ((soap->imode & SOAP_IO) == SOAP_IO_CHUNK) + soap->omode |= SOAP_IO_CHUNK; + soap->imode &= ~SOAP_IO; + soap->mode = soap->imode; + if (!soap->keep_alive) + { soap->buflen = 0; + soap->bufidx = 0; + } + if (!(soap->mode & SOAP_IO_KEEPALIVE)) + soap->keep_alive = 0; + soap->ahead = 0; + soap->peeked = 0; + soap->level = 0; + soap->part = SOAP_BEGIN; + soap->alloced = 0; + soap->count = 0; + soap->length = 0; + soap->cdata = 0; + *soap->endpoint = '\0'; + soap->userid = NULL; + soap->passwd = NULL; + soap->action = NULL; + soap->authrealm = NULL; +#ifndef WITH_LEANER + soap->dime.chunksize = 0; + soap->dime.buflen = 0; + soap->dime.list = NULL; + soap->dime.first = NULL; + soap->dime.last = NULL; + soap->mime.list = NULL; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = NULL; + soap->mime.start = NULL; +#endif +#ifdef WIN32 +#ifndef UNDER_CE +#ifndef WITH_FASTCGI + if (!soap_valid_socket(soap->socket)) +#ifdef __BORLANDC__ + setmode((SOAP_SOCKET)soap->recvfd, O_BINARY); +#else + _setmode((SOAP_SOCKET)soap->recvfd, _O_BINARY); +#endif +#endif +#endif +#endif +#ifdef WITH_ZLIB + soap->mode &= ~SOAP_ENC_ZLIB; + soap->zlib_in = SOAP_ZLIB_NONE; + soap->zlib_out = SOAP_ZLIB_NONE; + soap->d_stream.next_in = Z_NULL; + soap->d_stream.avail_in = 0; + soap->d_stream.next_out = (Byte*)soap->buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + soap->z_ratio_in = 1.0; +#endif +#ifndef WITH_LEANER + if (soap->fprepareinit) + soap->fprepareinit(soap); +#endif + c = soap_getchar(soap); +#ifdef WITH_GZIP + if (c == 0x1F) + { if (soap_getgziphdr(soap)) + return soap->error; + if (inflateInit2(&soap->d_stream, -MAX_WBITS) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; + soap->zlib_state = SOAP_ZLIB_INFLATE; + soap->mode |= SOAP_ENC_ZLIB; + soap->zlib_in = SOAP_ZLIB_GZIP; + soap->z_crc = crc32(0L, NULL, 0); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n")); + memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); + /* should not chunk over plain transport, so why bother to check? */ + /* if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) */ + /* soap->z_buflen = soap->bufidx; */ + /* else */ + soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx); + soap->d_stream.avail_in = soap->buflen - soap->bufidx; + soap->z_buflen = soap->buflen; + soap->buflen = soap->bufidx; + c = soap_getchar(soap); + } +#endif +#ifndef WITH_LEANER + if (c == '-' && soap_get0(soap) == '-') + soap->mode |= SOAP_ENC_MIME; + else if ((c & 0xFFFC) == (SOAP_DIME_VERSION | SOAP_DIME_MB) && (soap_get0(soap) & 0xFFF0) == 0x20) + soap->mode |= SOAP_ENC_DIME; + else +#endif + { while (soap_blank(c)) + c = soap_getchar(soap); + } + if ((int)c == EOF) + return soap->error = SOAP_EOF; + soap_unget(soap, c); +#ifndef WITH_NOHTTP + if (c != '<' && !(soap->mode & (SOAP_ENC_DIME | SOAP_ENC_ZLIB))) + { soap->mode &= ~SOAP_IO; + if ((soap->error = soap->fparse(soap))) + { soap->keep_alive = 0; /* force close later */ + return soap->error; + } + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) + { soap->chunkbuflen = soap->buflen; + soap->buflen = soap->bufidx; + soap->chunksize = 0; + } +#ifndef WITH_LEANER + else if (soap->fpreparerecv && soap->buflen != soap->bufidx) + soap->fpreparerecv(soap, soap->buf + soap->bufidx, soap->buflen - soap->bufidx); +#endif +#ifdef WITH_ZLIB + if (soap->zlib_in) + { /* fparse should not use soap_unget to push back last char */ +#ifdef WITH_GZIP + c = soap_get1(soap); + if (c == 0x1F) + { if (soap_getgziphdr(soap)) + return soap->error; + if (inflateInit2(&soap->d_stream, -MAX_WBITS) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; + soap->zlib_state = SOAP_ZLIB_INFLATE; + soap->z_crc = crc32(0L, NULL, 0); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n")); + } + else + { soap_revget1(soap); +#else + { +#endif + if (inflateInit(&soap->d_stream) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; + soap->zlib_state = SOAP_ZLIB_INFLATE; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate initialized\n")); + } + soap->mode |= SOAP_ENC_ZLIB; + memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); + soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx); + soap->d_stream.avail_in = soap->buflen - soap->bufidx; + soap->z_buflen = soap->buflen; + soap->buflen = soap->bufidx; + } +#endif + } +#endif +#ifndef WITH_LEANER + if (soap->mode & SOAP_ENC_MIME) + { if (soap_getmimehdr(soap)) + return soap->error; + if (soap_get_header_attribute(soap, soap->mime.first->type, "application/dime")) + soap->mode |= SOAP_ENC_DIME; + } + if (soap->mode & SOAP_ENC_DIME) + { if (soap_getdimehdr(soap)) + return soap->error; + if (soap->dime.flags & SOAP_DIME_CF) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked DIME SOAP message\n")); + soap->dime.chunksize = soap->dime.size; + if (soap->buflen - soap->bufidx >= soap->dime.chunksize) + { soap->dime.buflen = soap->buflen; + soap->buflen = soap->bufidx + soap->dime.chunksize; + } + else + soap->dime.chunksize -= soap->buflen - soap->bufidx; + } + soap->count = soap->buflen - soap->bufidx; + } +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_parse(struct soap *soap) +{ char header[SOAP_HDRLEN], *s; + unsigned short g = 0, k; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Waiting for response...\n")); + *soap->endpoint = '\0'; + soap->length = 0; + do + { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) + return soap->error; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP status: %s\n", soap->msgbuf)); + for (;;) + { if (soap_getline(soap, header, SOAP_HDRLEN)) + { if (soap->error == SOAP_EOF) + { soap->error = SOAP_OK; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "EOF in HTTP header, continue anyway\n")); + break; + } + return soap->error; + } + if (!*header) + break; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP header: %s\n", header)); + s = strchr(header, ':'); + if (s) + { *s = '\0'; + do s++; + while (*s && *s <= 32); + if ((soap->error = soap->fparsehdr(soap, header, s))) + return soap->error; + } + } + if ((s = strchr(soap->msgbuf, ' '))) + k = (unsigned short)soap_strtoul(s, NULL, 10); + else + k = 0; + } while (k == 100); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Finished HTTP header parsing\n")); + s = strstr(soap->msgbuf, "HTTP/"); + if (s && s[7] != '1') + { if (soap->keep_alive == 1) + soap->keep_alive = 0; + if (k == 0 && (soap->omode & SOAP_IO) == SOAP_IO_CHUNK) /* k == 0 for HTTP request */ + { soap->imode |= SOAP_IO_CHUNK; + soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE; + } + } + if (soap->keep_alive < 0) + soap->keep_alive = 1; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Keep alive connection = %d\n", soap->keep_alive)); + if (s && (((g = !strncmp(soap->msgbuf, "GET ", 4))) || !strncmp(soap->msgbuf, "POST ", 5))) + { size_t m = strlen(soap->endpoint); + size_t n = m + (s - soap->msgbuf) - 5 - (!g); + if (n >= sizeof(soap->endpoint)) + n = sizeof(soap->endpoint) - 1; + strncpy(soap->path, soap->msgbuf + 4 + (!g), n - m); + soap->path[n - m] = '\0'; + strcat(soap->endpoint, soap->path); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Target endpoint='%s'\n", soap->endpoint)); + if (g) + { soap->error = soap->fget(soap); + if (soap->error == SOAP_OK) + soap->error = SOAP_STOP; /* prevents further processing */ + return soap->error; + } + return SOAP_OK; + } + if (k == 0 || (k >= 200 && k <= 299) || k == 400 || k == 500) + return SOAP_OK; + return soap_set_receiver_error(soap, "HTTP error", soap->msgbuf, k); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_parse_header(struct soap *soap, const char *key, const char *val) +{ if (!soap_tag_cmp(key, "Host")) + { +#ifdef WITH_OPENSSL + if (soap->imode & SOAP_ENC_SSL) + strcpy(soap->endpoint, "https://"); + else +#endif + strcpy(soap->endpoint, "http://"); + strncat(soap->endpoint, val, sizeof(soap->endpoint) - 8); + soap->endpoint[sizeof(soap->endpoint) - 1] = '\0'; + } +#ifndef WITH_LEANER + else if (!soap_tag_cmp(key, "Content-Type")) + { if (soap_get_header_attribute(soap, val, "application/dime")) + soap->mode |= SOAP_ENC_DIME; + else if (soap_get_header_attribute(soap, val, "multipart/related")) + { soap->mime.boundary = soap_strdup(soap, soap_get_header_attribute(soap, val, "boundary")); + soap->mime.start = soap_strdup(soap, soap_get_header_attribute(soap, val, "start")); + soap->mode |= SOAP_ENC_MIME; + } + } +#endif + else if (!soap_tag_cmp(key, "Content-Length")) + soap->length = soap_strtoul(val, NULL, 10); + else if (!soap_tag_cmp(key, "Content-Encoding")) + { if (!soap_tag_cmp(val, "deflate")) +#ifdef WITH_ZLIB + soap->zlib_in = SOAP_ZLIB_DEFLATE; +#else + return SOAP_ZLIB_ERROR; +#endif + else if (!soap_tag_cmp(val, "gzip")) +#ifdef WITH_GZIP + soap->zlib_in = SOAP_ZLIB_GZIP; +#else + return SOAP_ZLIB_ERROR; +#endif + } +#ifdef WITH_ZLIB + else if (!soap_tag_cmp(key, "Accept-Encoding")) + { +#ifdef WITH_GZIP + if (strchr(val, '*') || soap_get_header_attribute(soap, val, "gzip")) + soap->zlib_out = SOAP_ZLIB_GZIP; + else +#endif + if (strchr(val, '*') || soap_get_header_attribute(soap, val, "deflate")) + soap->zlib_out = SOAP_ZLIB_DEFLATE; + else + soap->zlib_out = SOAP_ZLIB_NONE; + } +#endif + else if (!soap_tag_cmp(key, "Transfer-Encoding")) + { soap->mode &= ~SOAP_IO; + if (!soap_tag_cmp(val, "chunked")) + soap->mode |= SOAP_IO_CHUNK; + } + else if (!soap_tag_cmp(key, "Connection")) + { if (!soap_tag_cmp(val, "keep-alive")) + soap->keep_alive = -soap->keep_alive; + else if (!soap_tag_cmp(val, "close")) + soap->keep_alive = 0; + } +#ifndef WITH_LEAN + else if (!soap_tag_cmp(key, "Authorization")) + { if (!soap_tag_cmp(val, "Basic *")) + { size_t n; + char *s; + soap_base642s(soap, val + 6, soap->tmpbuf, sizeof(soap->tmpbuf) - 1, &n); + soap->tmpbuf[n] = '\0'; + if ((s = strchr(soap->tmpbuf, ':'))) + { *s = '\0'; + soap->userid = soap_strdup(soap, soap->tmpbuf); + soap->passwd = soap_strdup(soap, s + 1); + } + } + } + else if (!soap_tag_cmp(key, "WWW-Authenticate")) + soap->authrealm = soap_strdup(soap, soap_get_header_attribute(soap, val+6, "realm")); + else if (!soap_tag_cmp(key, "Expect")) + { if (!soap_tag_cmp(val, "100-continue")) + { if ((soap->error = soap->fposthdr(soap, "HTTP/1.1 100 Continue", NULL)) + || (soap->error = soap->fposthdr(soap, NULL, NULL))) + return soap->error; + } + } +#endif + else if (!soap_tag_cmp(key, "SOAPAction")) + { if (val[0] && val[1]) + { soap->action = soap_strdup(soap, val + 1); + soap->action[strlen(soap->action) - 1] = '\0'; + } + } + else if (!soap_tag_cmp(key, "Location")) + { strncpy(soap->endpoint, val, sizeof(soap->endpoint)); + soap->endpoint[sizeof(soap->endpoint) - 1] = '\0'; + } +#ifdef WITH_COOKIES + else if (!soap_tag_cmp(key, "Cookie") || !soap_tag_cmp(key, "Set-Cookie")) + soap_getcookies(soap, val); +#endif + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_get_header_attribute(struct soap *soap, const char *line, const char *key) +{ register const char *s = line; + if (s) + { while (*s) + { register short flag; + s = soap_decode_key(soap->tmpbuf, sizeof(soap->tmpbuf), s); + flag = soap_tag_cmp(soap->tmpbuf, key); + s = soap_decode_val(soap->tmpbuf, sizeof(soap->tmpbuf), s); + if (!flag) + return soap->tmpbuf; + } + } + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_decode_key(char *buf, size_t len, const char *val) +{ return soap_decode(buf, len, val, "=,;"); +} +#endif +#endif + +/******************************************************************************/ +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_decode_val(char *buf, size_t len, const char *val) +{ if (*val != '=') + { *buf = '\0'; + return val; + } + return soap_decode(buf, len, val + 1, ",;"); +} +#endif +#endif + +/******************************************************************************/ +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +#ifndef PALM_1 +static const char* +soap_decode(char *buf, size_t len, const char *val, const char *sep) +{ const char *s; + char *t = buf; + for (s = val; *s; s++) + if (*s != ' ' && *s != '\t' && !strchr(sep, *s)) + break; + if (*s == '"') + { s++; + while (*s && *s != '"' && --len) + *t++ = *s++; + } + else + { while (soap_notblank(*s) && !strchr(sep, *s) && --len) + { if (*s == '%') + { *t++ = ((s[1] >= 'A' ? (s[1] & 0x7) + 9 : s[1] - '0') << 4) + + (s[2] >= 'A' ? (s[2] & 0x7) + 9 : s[2] - '0'); + s += 3; + } + else + *t++ = *s++; + } + } + *t = '\0'; + while (*s && !strchr(sep, *s)) + s++; + return s; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_envelope_begin_out(struct soap *soap) +{ +#ifndef WITH_LEANER + size_t n = 0; + if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && soap->mime.start) + { const char *s; + if (soap->mode & SOAP_ENC_DIME) + s = "application/dime"; + else if (soap->version == 2) + s = "application/soap+xml; charset=utf-8"; + else + s = "text/xml; charset=utf-8"; + sprintf(soap->tmpbuf, "--%s\r\nContent-Type: %s\r\nContent-Transfer-Encoding: binary\r\nContent-ID: %s\r\n\r\n", soap->mime.boundary, s, soap->mime.start); + n = strlen(soap->tmpbuf); + if (soap_send_raw(soap, soap->tmpbuf, n)) + return soap->error; + } + if (soap->mode & SOAP_IO_LENGTH) + soap->dime.size = soap->count; /* DIME in MIME correction */ + if (!(soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME)) + { if (soap_putdimehdr(soap)) + return soap->error; + } +#endif + soap->part = SOAP_IN_ENVELOPE; + return soap_element_begin_out(soap, "SOAP-ENV:Envelope", 0, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_envelope_end_out(struct soap *soap) +{ if (soap_element_end_out(soap, "SOAP-ENV:Envelope")) + return soap->error; +#ifndef WITH_LEANER + if ((soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME)) + { soap->dime.size = soap->count - soap->dime.size; /* DIME in MIME correction */ + sprintf(soap->id, soap->dime_id_format, 0); + soap->dime.id = soap->id; + if (soap->local_namespaces) + { if (soap->local_namespaces[0].out) + soap->dime.type = (char*)soap->local_namespaces[0].out; + else + soap->dime.type = (char*)soap->local_namespaces[0].ns; + } + soap->dime.options = NULL; + soap->dime.flags = SOAP_DIME_MB | SOAP_DIME_ABSURI; + if (!soap->dime.first) + soap->dime.flags |= SOAP_DIME_ME; + soap->count += 12 + ((strlen(soap->dime.id)+3)&(~3)) + ((strlen(soap->dime.type)+3)&(~3)); + } + if (soap->mode & SOAP_ENC_DIME) + return soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3); +#endif + soap->part = SOAP_END_ENVELOPE; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_envelope_begin_in(struct soap *soap) +{ register struct Namespace *p; + soap->part = SOAP_IN_ENVELOPE; + if (soap_element_begin_in(soap, "SOAP-ENV:Envelope", 0)) + return soap->error = SOAP_VERSIONMISMATCH; + p = soap->local_namespaces; + if (p) + { const char *ns = p[0].out; + if (!ns) + ns = p[0].ns; + if (!strcmp(ns, soap_env1)) + { soap->version = 1; /* make sure we use SOAP 1.1 */ + if (p[1].out) + SOAP_FREE(p[1].out); + if ((p[1].out = (char*)SOAP_MALLOC(sizeof(soap_enc1)))) + strcpy(p[1].out, soap_enc1); + } + else if (!strcmp(ns, soap_env2)) + { soap->version = 2; /* make sure we use SOAP 1.2 */ + if (p[1].out) + SOAP_FREE(p[1].out); + if ((p[1].out = (char*)SOAP_MALLOC(sizeof(soap_enc2)))) + strcpy(p[1].out, soap_enc2); + } + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_envelope_end_in(struct soap *soap) +{ if (soap_element_end_in(soap, "SOAP-ENV:Envelope")) + return soap->error; + soap->part = SOAP_END_ENVELOPE; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_body_begin_out(struct soap *soap) +{ soap->part = SOAP_IN_BODY; + if (soap->version == 1) + soap->encoding = 1; + if (soap_element(soap, "SOAP-ENV:Body", 0, NULL)) + return soap->error; + if ((soap->mode & SOAP_XML_SEC) && soap_attribute(soap, "id", "_0")) + return soap->error; + return soap_element_start_end_out(soap, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_body_end_out(struct soap *soap) +{ if (soap_element_end_out(soap, "SOAP-ENV:Body")) + return soap->error; + soap->part = SOAP_IN_BODY; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_body_begin_in(struct soap *soap) +{ soap->part = SOAP_IN_BODY; + return soap_element_begin_in(soap, "SOAP-ENV:Body", 0); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_body_end_in(struct soap *soap) +{ if (soap_element_end_in(soap, "SOAP-ENV:Body")) + return soap->error; + soap->part = SOAP_END_BODY; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv_header(struct soap *soap) +{ if (soap_getheader(soap) && soap->error == SOAP_TAG_MISMATCH) + soap->error = SOAP_OK; + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_endpoint(struct soap *soap, const char *endpoint) +{ register const char *s; + register size_t i, n; + *soap->endpoint = '\0'; + *soap->host = '\0'; + *soap->path = '\0'; + soap->port = 80; + if (!endpoint || !*endpoint) + return; +#ifdef WITH_OPENSSL + if (!strncmp(endpoint, "https:", 6)) + soap->port = 443; +#endif + strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint) - 1); + s = strchr(endpoint, ':'); + if (s && s[1] == '/' && s[2] == '/') + s += 3; + else + s = endpoint; + n = strlen(s); + if (n >= sizeof(soap->host)) + n = sizeof(soap->host) - 1; +/* WR[ */ +#ifdef WITH_IPV6 + if ('[' == s[0]) + { s++; + for (i = 0; i < n; i++) + { soap->host[i] = s[i]; + if (']' == s[i]) + { + s++; + break; + } + } + } + else + { for (i = 0; i < n; i++) + { soap->host[i] = s[i]; + if (s[i] == '/' || s[i] == ':') + break; + } + } +#else /* WITH_IPV6 */ +/* ]WR */ + for (i = 0; i < n; i++) + { soap->host[i] = s[i]; + if (s[i] == '/' || s[i] == ':') + break; + } +/* WR[ */ +#endif /* WITH_IPV6 */ +/* ]WR */ + soap->host[i] = '\0'; + if (s[i] == ':') + { soap->port = (int)atol(s + i + 1); + for (i++; i < n; i++) + if (s[i] == '/') + break; + } + if (s[i]) + { strncpy(soap->path, s + i + 1, sizeof(soap->path)); + soap->path[sizeof(soap->path) - 1] = '\0'; + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_connect(struct soap *soap, const char *endpoint, const char *action) +{ return soap_connect_command(soap, SOAP_POST, endpoint, action); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_connect_command(struct soap *soap, int http_command, const char *endpoint, const char *action) +{ char host[sizeof(soap->host)]; + int port; + size_t count; + soap->error = SOAP_OK; + strcpy(host, soap->host); /* save to compare */ + port = soap->port; /* save to compare */ + soap_set_endpoint(soap, endpoint); + if (action) + soap->action = soap_strdup(soap, action); +#ifndef WITH_LEANER + if (soap->fconnect) + { if ((soap->error = soap->fconnect(soap, endpoint, soap->host, soap->port))) + return soap->error; + } + else +#endif + if (soap->fopen && *soap->host) + { soap->status = http_command; + if (!soap->keep_alive || !soap_valid_socket(soap->socket) || strcmp(soap->host, host) || soap->port != port || !soap->fpoll || soap->fpoll(soap)) + { soap->keep_alive = 0; /* force close */ + soap_closesock(soap); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Connect/reconnect to host='%s' path='%s' port=%d\n", soap->host, soap->path, soap->port)); + soap->socket = soap->fopen(soap, endpoint, soap->host, soap->port); + if (soap->error) + return soap->error; + soap->keep_alive = ((soap->omode & SOAP_IO_KEEPALIVE) != 0); + } + } + if (soap_begin_send(soap)) + return soap->error; + count = soap_count_attachments(soap); +#ifndef WITH_NOHTTP + if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML) && endpoint) + { unsigned int k = soap->mode; + soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB); + if ((k & SOAP_IO) != SOAP_IO_FLUSH) + soap->mode |= SOAP_IO_BUFFER; + if ((soap->error = soap->fpost(soap, endpoint, soap->host, soap->port, soap->path, action, count))) + return soap->error; +#ifndef WITH_LEANER + if ((k & SOAP_IO) == SOAP_IO_CHUNK) + { if (soap_flush(soap)) + return soap->error; + } +#endif + soap->mode = k; + } + if (http_command != SOAP_POST) + return soap_end_send(soap); +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_s2base64(struct soap *soap, const unsigned char *s, char *t, size_t n) +{ register size_t i; + register unsigned long m; + register char *p; + if (!t) + t = (char*)soap_malloc(soap, (n + 2) / 3 * 4 + 1); + if (!t) + { soap->error = SOAP_EOM; + return NULL; + } + p = t; + t[0] = '\0'; + if (!s) + return p; + for (; n > 2; n -= 3, s += 3) + { m = s[0]; + m = (m << 8) | s[1]; + m = (m << 8) | s[2]; + for (i = 4; i > 0; m >>= 6) + t[--i] = soap_base64o[m & 0x3F]; + t += 4; + } + t[0] = '\0'; + if (n > 0) + { m = 0; + for (i = 0; i < n; i++) + m = (m << 8) | *s++; + for (; i < 3; i++) + m <<= 8; + for (i++; i > 0; m >>= 6) + t[--i] = soap_base64o[m & 0x3F]; + for (i = 3; i > n; i--) + t[i] = '='; + t[4] = '\0'; + } + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_base642s(struct soap *soap, const char *s, char *t, size_t l, size_t *n) +{ register int i, j, c; + register unsigned long m; + char *p = t; + if (n) + *n = 0; + for (;;) + { for (i = 0; i < SOAP_BLKLEN; i++) + { m = 0; + j = 0; + while (j < 4) + { c = *s++; + if (c == '=' || !c) + { i *= 3; + switch (j) + { case 2: + *t++ = (char)((m >> 4) & 0xFF); + i++; + break; + case 3: + *t++ = (char)((m >> 10) & 0xFF); + *t++ = (char)((m >> 2) & 0xFF); + i += 2; + } + if (n) + *n += i; + return p; + } + c -= '+'; + if (c >= 0 && c <= 79) + { m = (m << 6) + soap_base64i[c]; + j++; + } + } + *t++ = (char)((m >> 16) & 0xFF); + *t++ = (char)((m >> 8) & 0xFF); + *t++ = (char)(m & 0xFF); + if (l < 3) + { if (n) + *n += i; + return p; + } + l -= 3; + } + if (n) + *n += 3 * SOAP_BLKLEN; + } +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_puthttphdr(struct soap *soap, int status, size_t count) +{ register const char *s; + register int err; + if (status == SOAP_FILE && soap->http_content) + s = soap->http_content; + else if (status == SOAP_HTML) + s = "text/html; charset=utf-8"; +#ifndef WITH_LEANER + else if (soap->mode & SOAP_ENC_DIME) + s = "application/dime"; +#endif + else if (soap->version == 2) + s = "application/soap+xml; charset=utf-8"; + else + s = "text/xml; charset=utf-8"; +#ifndef WITH_LEANER + if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && soap->status != SOAP_GET) + { register const char *t = strchr(s, ';'); + sprintf(soap->tmpbuf, "multipart/related; boundary=\"%s\"; type=\"", soap->mime.boundary); + if (t) + strncat(soap->tmpbuf, s, t - s); + else + strcat(soap->tmpbuf, s); + if (soap->mime.start) + { strcat(soap->tmpbuf, "\"; start=\""); + strcat(soap->tmpbuf, soap->mime.start); + } + strcat(soap->tmpbuf, "\""); + s = soap->tmpbuf; + } +#endif + if ((err = soap->fposthdr(soap, "Content-Type", s))) + return err; +#ifdef WITH_ZLIB + if (soap->omode & SOAP_ENC_ZLIB) + { +#ifdef WITH_GZIP + err = soap->fposthdr(soap, "Content-Encoding", "gzip"); +#else + err = soap->fposthdr(soap, "Content-Encoding", "deflate"); +#endif + if (err) + return err; + } +#endif +#ifndef WITH_LEANER + if ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK) + err = soap->fposthdr(soap, "Transfer-Encoding", "chunked"); + else +#endif + if (count > 0) + { sprintf(soap->tmpbuf, "%lu", (unsigned long)count); + err = soap->fposthdr(soap, "Content-Length", soap->tmpbuf); + } + if (err) + return err; + return soap->fposthdr(soap, "Connection", soap->keep_alive ? "keep-alive" : "close"); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_get(struct soap *soap) +{ return SOAP_GET_METHOD; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_post(struct soap *soap, const char *endpoint, const char *host, int port, const char *path, const char *action, size_t count) +{ register const char *s; + register int err; + if (soap->status == SOAP_GET) + { s = "GET"; + count = 0; + } + else + s = "POST"; +#ifdef PALM + if (!endpoint || (strncmp(endpoint, "http:", 5) && strncmp(endpoint, "https:", 6) && strncmp(endpoint, "httpg:", 6)) && strncmp(endpoint, "_beam:", 6) && strncmp(endpoint, "_local:", 7) && strncmp(endpoint, "_btobex:", 8)) +#else + if (!endpoint || (strncmp(endpoint, "http:", 5) && strncmp(endpoint, "https:", 6) && strncmp(endpoint, "httpg:", 6))) +#endif + return SOAP_OK; + if (soap->proxy_host && strncmp(endpoint, "https:", 6)) + sprintf(soap->tmpbuf, "%s %s HTTP/%s", s, endpoint, soap->http_version); + else + sprintf(soap->tmpbuf, "%s /%s HTTP/%s", s, path, soap->http_version); + if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return err; + if (port != 80) + sprintf(soap->tmpbuf, "%s:%d", host, port); + else + strcpy(soap->tmpbuf, host); + if ((err = soap->fposthdr(soap, "Host", soap->tmpbuf)) + || (err = soap->fposthdr(soap, "User-Agent", "gSOAP/2.7")) + || (err = soap_puthttphdr(soap, SOAP_OK, count))) + return err; +#ifdef WITH_ZLIB +#ifdef WITH_GZIP + if ((err = soap->fposthdr(soap, "Accept-Encoding", "gzip, deflate"))) +#else + if ((err = soap->fposthdr(soap, "Accept-Encoding", "deflate"))) +#endif + return err; +#endif +#ifndef WITH_LEAN + if (soap->userid && soap->passwd && strlen(soap->userid) + strlen(soap->passwd) < 761) + { sprintf(soap->tmpbuf + 262, "%s:%s", soap->userid, soap->passwd); + strcpy(soap->tmpbuf, "Basic "); + soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, strlen(soap->tmpbuf + 262)); + if ((err = soap->fposthdr(soap, "Authorization", soap->tmpbuf))) + return err; + } + if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761) + { sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd); + strcpy(soap->tmpbuf, "Basic "); + soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, strlen(soap->tmpbuf + 262)); + if ((err = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf))) + return err; + } +#endif +#ifdef WITH_COOKIES +#ifdef WITH_OPENSSL + if (soap_putcookies(soap, host, path, soap->ssl != NULL)) + return soap->error; +#else + if (soap_putcookies(soap, host, path, 0)) + return soap->error; +#endif +#endif + if (action && soap->version == 1) + { sprintf(soap->tmpbuf, "\"%s\"", action); + if ((err = soap->fposthdr(soap, "SOAPAction", soap->tmpbuf))) + return err; + } + return soap->fposthdr(soap, NULL, NULL); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_send_header(struct soap *soap, const char *s) +{ register const char *t; + do + { t = strchr(s, '\n'); /* disallow \n in HTTP headers */ + if (!t) + t = s + strlen(s); + if (soap_send_raw(soap, s, t - s)) + return soap->error; + s = t + 1; + } while (*t); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_post_header(struct soap *soap, const char *key, const char *val) +{ if (key) + { if (http_send_header(soap, key)) + return soap->error; + if (val && (soap_send_raw(soap, ": ", 2) || http_send_header(soap, val))) + return soap->error; + } + return soap_send_raw(soap, "\r\n", 2); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_response(struct soap *soap, int status, size_t count) +{ register int err; +/* WR[ */ +#ifdef WMW_RPM_IO + if (soap->rpmreqid) + httpOutputEnable(soap->rpmreqid); +#endif /* WMW_RPM_IO */ +/* ]WR */ + if (!status || status == SOAP_HTML || status == SOAP_FILE) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "OK 200\n")); +/* WR[ */ +#ifdef WMW_RPM_IO + if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */ +#else +/* ]WR */ + if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application */ +/* WR[ */ +#endif /* WMW_RPM_IO */ +/* ]WR */ + { sprintf(soap->tmpbuf, "HTTP/%s 200 OK", soap->http_version); + if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return err; + } + else if ((err = soap->fposthdr(soap, "Status", "200 OK"))) + return err; + } + else if (status > 200 && status < 600) + { sprintf(soap->tmpbuf, "HTTP/%s %d %s", soap->http_version, status, http_error(soap, status)); + if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return err; +#ifndef WITH_LEAN + if (status == 401) + { sprintf(soap->tmpbuf, "Basic realm=\"%s\"", soap->authrealm ? soap->authrealm : "gSOAP Web Service"); + if ((err = soap->fposthdr(soap, "WWW-Authenticate", soap->tmpbuf))) + return err; + } + else if ((status >= 301 && status <= 303) || status == 307) + { if ((err = soap->fposthdr(soap, "Location", soap->endpoint))) + return err; + } +#endif + } + else + { const char *s = *soap_faultcode(soap); + if (soap->version == 2 && !strcmp(s, "SOAP-ENV:Sender")) + s = "400 Bad Request"; + else + s = "500 Internal Server Error"; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error %s (status=%d)\n", s, status)); +/* WR[ */ +#ifdef WMW_RPM_IO + if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */ +#else +/* ]WR */ + if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application */ +/* WR[ */ +#endif /* WMW_RPM_IO */ +/* ]WR */ + { sprintf(soap->tmpbuf, "HTTP/%s %s", soap->http_version, s); + if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return err; + } + else if ((err = soap->fposthdr(soap, "Status", s))) + return err; + } + if ((err = soap->fposthdr(soap, "Server", "gSOAP/2.7")) + || (err = soap_puthttphdr(soap, status, count))) + return err; +#ifdef WITH_COOKIES + if (soap_putsetcookies(soap)) + return soap->error; +#endif + return soap->fposthdr(soap, NULL, NULL); +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_response(struct soap *soap, int status) +{ register size_t count; + if (!(soap->omode & (SOAP_ENC_XML | SOAP_IO_STORE /* this tests for chunking too */)) + && (status == SOAP_HTML || status == SOAP_FILE)) + { soap->omode &= ~SOAP_IO; + soap->omode |= SOAP_IO_STORE; + } + soap->status = status; + count = soap_count_attachments(soap); + if (soap_begin_send(soap)) + return soap->error; +#ifndef WITH_NOHTTP + if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML)) + { register int n = soap->mode; + soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB); + if ((n & SOAP_IO) != SOAP_IO_FLUSH) + soap->mode |= SOAP_IO_BUFFER; + if ((soap->error = soap->fresponse(soap, status, count))) + return soap->error; +#ifndef WITH_LEANER + if ((n & SOAP_IO) == SOAP_IO_CHUNK) + { if (soap_flush(soap)) + return soap->error; + } +#endif + soap->mode = n; + } +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static const char* +soap_set_validation_fault(struct soap *soap, const char *s, const char *t) +{ sprintf(soap->msgbuf, "Validation constraint violation: %s%s in element <%s>", s, t?t:SOAP_STR_EOS, soap->tag); + return soap->msgbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_fault(struct soap *soap) +{ const char **c = soap_faultcode(soap); + const char **s = soap_faultstring(soap); + if (!*c) + { if (soap->version == 2) + *c = "SOAP-ENV:Sender"; + else + *c = "SOAP-ENV:Client"; + } + if (*s) + return; + switch (soap->error) + { +#ifndef WITH_LEAN + case SOAP_CLI_FAULT: + *s = "Client fault"; + break; + case SOAP_SVR_FAULT: + *s = "Server fault"; + break; + case SOAP_TAG_MISMATCH: + *s = soap_set_validation_fault(soap, "tag name or namespace mismatch", NULL); + break; + case SOAP_TYPE: + *s = soap_set_validation_fault(soap, "data type mismatch ", soap->type); + break; + case SOAP_SYNTAX_ERROR: + *s = "Well-formedness constraint violation"; + break; + case SOAP_NO_TAG: + *s = "No XML element tag found"; + break; + case SOAP_MUSTUNDERSTAND: + *c = "SOAP-ENV:MustUnderstand"; + sprintf(soap->msgbuf, "The data in element '%s' must be understood but cannot be handled", soap->tag); + *s = soap->msgbuf; + break; + case SOAP_VERSIONMISMATCH: + *c = "SOAP-ENV:VersionMismatch"; + *s = "SOAP version mismatch or invalid SOAP message"; + break; + case SOAP_DATAENCODINGUNKNOWN: + *c = "SOAP-ENV:DataEncodingUnknown"; + *s = "Unsupported SOAP data encoding"; + break; + case SOAP_NAMESPACE: + *s = soap_set_validation_fault(soap, "namespace mismatch", NULL); + break; + case SOAP_FATAL_ERROR: + *s = "Fatal error"; + break; + case SOAP_NO_METHOD: + sprintf(soap->msgbuf, "Method '%s' not implemented: method name or namespace not recognized", soap->tag); + *s = soap->msgbuf; + break; + case SOAP_GET_METHOD: + *s = "HTTP GET method not implemented"; + break; + case SOAP_EOM: + *s = "Out of memory"; + break; + case SOAP_IOB: + *s = "Array index out of bounds"; + break; + case SOAP_NULL: + *s = soap_set_validation_fault(soap, "nil not allowed", NULL); + break; + case SOAP_MULTI_ID: + *s = soap_set_validation_fault(soap, "multiple definitions of id ", soap->id); + break; + case SOAP_MISSING_ID: + *s = soap_set_validation_fault(soap, "missing id for ref ", soap->id); + break; + case SOAP_HREF: + *s = soap_set_validation_fault(soap, "incompatible object ref ", soap->id); + break; + case SOAP_FAULT: + break; +#ifndef WITH_NOIO + case SOAP_TCP_ERROR: + *s = tcp_error(soap); + break; +#endif + case SOAP_HTTP_ERROR: + *s = "HTTP error"; + break; + case SOAP_SSL_ERROR: + *s = "SSL error"; + break; + case SOAP_PLUGIN_ERROR: + *s = "Plugin registry error"; + break; + case SOAP_DIME_MISMATCH: + *s = "DIME version/transmission error"; + break; + case SOAP_DIME_END: + *s = "End of DIME error"; + break; + case SOAP_DIME_ERROR: + *s = "DIME format error"; + break; + case SOAP_MIME_ERROR: + *s = "MIME format error"; + break; + case SOAP_ZLIB_ERROR: +#ifdef WITH_ZLIB + sprintf(soap->msgbuf, "Zlib/gzip error: '%s'", soap->d_stream.msg?soap->d_stream.msg:""); + *s = soap->msgbuf; +#else + *s = "Zlib not installed for required message (de)compression"; +#endif + break; + case SOAP_REQUIRED: + *s = soap_set_validation_fault(soap, "missing required attribute", NULL); + break; + case SOAP_PROHIBITED: + *s = soap_set_validation_fault(soap, "prohibited attribute present", NULL); + break; + case SOAP_OCCURS: + *s = soap_set_validation_fault(soap, "a min/maxOccurs violation was detected", NULL); + break; + case SOAP_LENGTH: + *s = soap_set_validation_fault(soap, "content length violation", NULL); + break; +#endif + case SOAP_EOF: +#ifndef WITH_NOIO + sprintf(soap->msgbuf, "End of file or no input: '%s'", soap_strerror(soap)); + *s = soap->msgbuf; + break; +#else + *s = "End of file or no input"; + break; +#endif + default: +#ifndef WITH_NOHTTP +#ifndef WITH_LEAN + if (soap->error > 200 && soap->error < 600) + { sprintf(soap->msgbuf, "HTTP Error: %d %s", soap->error, http_error(soap, soap->error)); + *s = soap->msgbuf; + } + else +#endif +#endif + { sprintf(soap->msgbuf, "Error code %d", soap->error); + *s = soap->msgbuf; + } + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send_fault(struct soap *soap) +{ register int status = soap->error; + if (status == SOAP_STOP) + return status; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Sending back fault struct for error code %d\n", soap->error)); + soap->keep_alive = 0; /* to terminate connection */ + soap_set_fault(soap); + if ((status != SOAP_EOF || (!soap->recv_timeout && !soap->send_timeout)) && (!soap->fpoll || soap->fpoll(soap) == SOAP_OK)) + { soap->error = SOAP_OK; + soap_serializeheader(soap); + soap_serializefault(soap); + soap_begin_count(soap); + if (soap->mode & SOAP_IO_LENGTH) + { soap_envelope_begin_out(soap); + soap_putheader(soap); + soap_body_begin_out(soap); + soap_putfault(soap); + soap_body_end_out(soap); + soap_envelope_end_out(soap); + } + if (soap_response(soap, status) + || soap_envelope_begin_out(soap) + || soap_putheader(soap) + || soap_body_begin_out(soap) + || soap_putfault(soap) + || soap_body_end_out(soap) + || soap_envelope_end_out(soap)) + return soap_closesock(soap); + soap_end_send(soap); + } + soap->error = status; + return soap_closesock(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv_fault(struct soap *soap) +{ register int status = soap->error; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Receiving SOAP Fault\n")); + soap->error = SOAP_OK; + if (soap_getfault(soap)) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Error: soap_get_soapfault() failed. Is this a SOAP message at all?\n")); + *soap_faultcode(soap) = (soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client"); + soap->error = status; + soap_set_fault(soap); + } + else + { register const char *s = *soap_faultcode(soap); + if (!soap_match_tag(soap, s, "SOAP-ENV:Server") || !soap_match_tag(soap, s, "SOAP-ENV:Receiver")) + status = SOAP_SVR_FAULT; + else if (!soap_match_tag(soap, s, "SOAP-ENV:Client") || !soap_match_tag(soap, s, "SOAP-ENV:Sender")) + status = SOAP_CLI_FAULT; + else if (!soap_match_tag(soap, s, "SOAP-ENV:MustUnderstand")) + status = SOAP_MUSTUNDERSTAND; + else if (!soap_match_tag(soap, s, "SOAP-ENV:VersionMismatch")) + status = SOAP_VERSIONMISMATCH; + else + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Fault code %s\n", s)); + status = SOAP_FAULT; + } + if (soap_body_end_in(soap) + || soap_envelope_end_in(soap) + || soap_end_recv(soap)) + return soap_closesock(soap); + soap->error = status; + } + return soap_closesock(soap); +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send_empty_response(struct soap *soap) +{ soap->count = 0; + if (soap_response(soap, SOAP_OK) || soap_end_send(soap)) + return soap_closesock(soap); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv_empty_response(struct soap *soap) +{ if (soap_begin_recv(soap) || soap_end_recv(soap)) + return soap_closesock(soap); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static const char* +soap_strerror(struct soap *soap) +{ + int err = soap->errnum; + if (!err) + err = soap_errno; + if (err) + { +#ifndef WIN32 + return strerror(err); +#else + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0, (LPTSTR)&soap->errorstr, sizeof(soap->errorstr), NULL); + return soap->errorstr; +#endif + } + return "Operation interrupted or timed out"; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +static int +soap_set_error(struct soap *soap, const char *faultcode, const char *faultstring, const char *faultdetail, int soaperror) +{ *soap_faultcode(soap) = faultcode; + *soap_faultstring(soap) = faultstring; + if (faultdetail && *faultdetail) + { register const char **s = soap_faultdetail(soap); + if (s) + *s = faultdetail; + } + return soap->error = soaperror; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_sender_error(struct soap *soap, const char *faultstring, const char *faultdetail, int soaperror) +{ return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", faultstring, faultdetail, soaperror); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_receiver_error(struct soap *soap, const char *faultstring, const char *faultdetail, int soaperror) +{ return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", faultstring, faultdetail, soaperror); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +static int +soap_copy_fault(struct soap *soap, const char *faultcode, const char *faultstring, const char *faultdetail) +{ char *s = NULL, *t = NULL; + if (faultstring) + s = soap_strdup(soap, faultstring); + if (faultdetail) + t = soap_strdup(soap, faultdetail); + return soap_set_error(soap, faultcode, s, t, SOAP_FAULT); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_sender_fault(struct soap *soap, const char *faultstring, const char *faultdetail) +{ return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", faultstring, faultdetail); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_receiver_fault(struct soap *soap, const char *faultstring, const char *faultdetail) +{ return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", faultstring, faultdetail); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +#ifndef WITH_NOIO +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_print_fault(struct soap *soap, FILE *fd) +{ if (soap->error) + { const char **s; + if (!*soap_faultcode(soap)) + soap_set_fault(soap); + fprintf(fd, "SOAP FAULT: %s\n\"%s\"\n", *soap_faultcode(soap), *soap_faultstring(soap)); + s = soap_faultdetail(soap); + if (s && *s) + fprintf(fd, "Detail: %s\n", *s); + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +#ifndef WITH_NOIO +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_print_fault_location(struct soap *soap, FILE *fd) +{ +#ifndef WITH_LEAN + int c; + if (soap->error && soap->buflen > 0) + { if (soap->bufidx == 0) + soap->bufidx = 1; + c = soap->buf[soap->bufidx - 1]; + soap->buf[soap->bufidx - 1] = '\0'; + if (soap->buflen - soap->bufidx > 1024) + soap->buf[soap->bufidx + 1024] = '\0'; + else + soap->buf[soap->buflen - 1] = '\0'; + fprintf(fd, "%s%c\n** HERE **\n", soap->buf, c); + if (soap->bufidx < soap->buflen) + fprintf(fd, "%s\n", soap->buf + soap->bufidx); + } +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_register_plugin_arg(struct soap *soap, int (*fcreate)(struct soap*, struct soap_plugin*, void*), void *arg) +{ register struct soap_plugin *p; + register int r; + if (!(p = (struct soap_plugin*)SOAP_MALLOC(sizeof(struct soap_plugin)))) + return soap->error = SOAP_EOM; + p->id = NULL; + p->data = NULL; + p->fcopy = NULL; + p->fdelete = NULL; + r = fcreate(soap, p, arg); + if (!r && p->fdelete) + { p->next = soap->plugins; + soap->plugins = p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Registered '%s' plugin\n", p->id)); + return SOAP_OK; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not register plugin '%s': plugin returned error %d (or fdelete callback not set)\n", p->id?p->id:"?", r)); + SOAP_FREE(p); + return r; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static void * +fplugin(struct soap *soap, const char *id) +{ register struct soap_plugin *p; + for (p = soap->plugins; p; p = p->next) + if (p->id == id || !strcmp(p->id, id)) + return p->data; + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void * +SOAP_FMAC2 +soap_lookup_plugin(struct soap *soap, const char *id) +{ return soap->fplugin(soap, id); +} +#endif + +/******************************************************************************/ +#ifdef __cplusplus +} +#endif + diff --git a/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.0f.h b/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.0f.h new file mode 100644 index 0000000..097b551 --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.0f.h @@ -0,0 +1,1885 @@ +/* + +stdsoap2.h 2.7.0f + +gSOAP runtime environment. + +gSOAP XML Web services tools +Copyright (C) 2000-2005, Robert van Engelen, Genivia, Inc., All Rights Reserved. + +Contributors: + +Wind River Systems, Inc., for the following additions (marked WR[...]) : + - vxWorks compatible + - Support for IPv6. + +-------------------------------------------------------------------------------- + + This software is released under one of the following three licenses: + GPL, the gSOAP public license, or Genivia's license for commercial use. + +-------------------------------------------------------------------------------- +gSOAP public license. + +The contents of this file are subject to the gSOAP Public License Version 1.3 +(the "License"); you may not use this file except in compliance with the +License. You may obtain a copy of the License at +http://www.cs.fsu.edu/~engelen/soaplicense.html +Software distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +for the specific language governing rights and limitations under the License. + +The Initial Developer of the Original Code is Robert A. van Engelen. +Copyright (C) 2000-2005, Robert van Engelen, Genivia, Inc., All Rights Reserved. +-------------------------------------------------------------------------------- +GPL license. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA + +Author contact information: +engelen@genivia.com / engelen@acm.org +-------------------------------------------------------------------------------- +A commercial use license is available from Genivia, Inc., contact@genivia.com +-------------------------------------------------------------------------------- +*/ + +#ifdef WITH_SOAPDEFS_H +# include "soapdefs.h" /* include user-defined stuff */ +#endif + +#ifndef _THREAD_SAFE +# define _THREAD_SAFE +#endif + +#ifndef OPENSERVER +# ifndef _REENTRANT +# define _REENTRANT +# endif +#endif + +#ifndef SOAP_BEGIN_NAMESPACE +# define SOAP_BEGIN_NAMESPACE(name) +#endif + +#ifndef SOAP_END_NAMESPACE +# define SOAP_END_NAMESPACE(name) +#endif + +#ifndef SOAP_FMAC1 /* stdsoap2.h declaration macro */ +# define SOAP_FMAC1 +#endif + +#ifndef SOAP_FMAC2 /* stdsoap2.h declaration macro */ +# define SOAP_FMAC2 +#endif + +#ifndef SOAP_FMAC3 /* (de)serializer declaration macro */ +# define SOAP_FMAC3 +#endif + +#ifndef SOAP_FMAC3S /* string converter for (de)serializer declaration macro */ +# define SOAP_FMAC3S SOAP_FMAC3 +#endif + +#ifndef SOAP_FMAC4 /* (de)serializer declaration macro */ +# define SOAP_FMAC4 +#endif + +#ifndef SOAP_FMAC4S /* string converter for (de)serializer declaration macro */ +# define SOAP_FMAC4S SOAP_FMAC4 +#endif + +#ifndef SOAP_FMAC5 /* stub/skeleton declaration macro */ +# define SOAP_FMAC5 +#endif + +#ifndef SOAP_FMAC6 /* stub/skeleton declaration macro */ +# define SOAP_FMAC6 +#endif + +#ifndef SOAP_CMAC /* class declaration macro */ +# define SOAP_CMAC +#endif + +#ifndef SOAP_NMAC /* namespace table declaration macro */ +# define SOAP_NMAC +#endif + +#ifndef SOAP_SOURCE_STAMP +# define SOAP_SOURCE_STAMP(str) +#endif + +#ifdef WITH_LEANER +# ifndef WITH_LEAN +# define WITH_LEAN +# endif +#endif + +#ifdef WITH_LEAN +# ifdef WITH_COOKIES +# error "Cannot build WITH_LEAN code WITH_COOKIES enabled" +# endif +#endif + +#ifndef STDSOAP_H +#define STDSOAP_H + +#if defined(__vxworks) || defined(__VXWORKS__) +# define VXWORKS +#endif + +#ifdef _WIN32 +# ifndef WIN32 +# define WIN32 +# endif +#endif + +#ifdef UNDER_CE +# ifndef WIN32 +# define WIN32 +# endif +#endif + +#ifdef __BORLANDC__ +# ifdef __WIN32__ +# ifndef WIN32 +# define WIN32 +# endif +# endif +#endif + +#ifdef __CYGWIN__ +# ifndef CYGWIN +# define CYGWIN +# endif +#endif + +#ifdef __SYMBIAN32__ +# define SYMBIAN +# undef WIN32 +#endif + +#if defined(__palmos__) || defined(PALM_GCC) || defined(__PALMOS_TRAPS__) +# ifndef PALM +# define PALM +# endif +#endif + +#if defined(__hpux) +# ifndef HP_UX +# define HP_UX +# endif +#endif + +#ifdef __alpha +# ifndef TRU64 +# define TRU64 +# endif +#endif + +#ifdef __MVS__ +# ifndef OS390 +# define OS390 +# endif +#endif + +#ifdef _AIX +# define __socklen_t_defined +#endif + +#ifdef HAVE_CONFIG_H +# include "config.h" +#else +# if defined(UNDER_CE) +# define WITH_LEAN +# define HAVE_SSCANF +# elif defined(WIN32) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(CYGWIN) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(__APPLE__) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_TIMEGM +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(_AIXVERSION_431) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(HP_UX) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(FREEBSD) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_GETTIMEOFDAY +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(__VMS) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(__GLIBC__) || defined(__GNU__) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_TIMEGM +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# define HAVE_ISNAN +# elif defined(TRU64) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_GETTIMEOFDAY +# define HAVE_SYS_TIMEB_H +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define __USE_STD_IOSTREAM +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(MAC_CARBON) +# define WITH_NOIO +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GETHOSTBYNAME_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(PALM) +# define WITH_LEAN +# define HAVE_STRTOD /* strtod() is defined in palmFunctions.h */ +# include /* Needs to be included before unix headers */ +# include +# define IGNORE_STDIO_STUBS +# include +# define O_NONBLOCK FNONBIO +# include +# include +# include "palmFunctions.h" +# elif defined(SYMBIAN) +# define WITH_LEAN +# define WITH_NONAMESPACES +# define HAVE_STRTOD /* use STRTOD since sscanf doesn't seem to work */ +# include +# include +# elif defined(VXWORKS) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_RAND_R +# define HAVE_PGMTIME_R +# define HAVE_PLOCALTIME_R +# define HAVE_MKTIME +# elif defined(OS390) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MB +# else +/* Default asumptions on supported functions */ +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GETHOSTBYNAME_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# endif +#endif + +#if defined(TRU64) +# define SOAP_LONG_FORMAT "%ld" +# define SOAP_ULONG_FORMAT "%lu" +#elif defined(WIN32) +# define SOAP_LONG_FORMAT "%I64d" +# define SOAP_ULONG_FORMAT "%I64u" +#endif + +#ifndef SOAP_LONG_FORMAT +# define SOAP_LONG_FORMAT "%lld" /* printf format for 64 bit ints */ +#endif + +#ifndef SOAP_ULONG_FORMAT +# define SOAP_ULONG_FORMAT "%llu" /* printf format for unsigned 64 bit ints */ +#endif + +#ifndef SOAP_MALLOC /* use libc malloc */ +# define SOAP_MALLOC(n) malloc(n) +#endif + +#ifndef SOAP_FREE /* use libc free */ +# define SOAP_FREE(p) free(p) +#endif + +#include + +#ifndef PALM +# include +# include +#endif + +#include +#include + +#if defined(__cplusplus) && !defined(WITH_LEAN) +# include +# include + using namespace std; +#endif + +#ifdef WITH_NOHTTP +# ifndef WITH_NOIO +# define WITH_NOIO +# undef WITH_COOKIES +# endif +#endif + +#ifndef UNDER_CE +# ifndef PALM +# ifndef WITH_NOIO +# include +# include +# endif +# ifndef WITH_LEAN +# ifdef HAVE_SYS_TIMEB_H +# include /* for ftime() */ +# endif +# include +# endif +# endif +#endif + +#ifdef OPENSERVER +# include +# include +# include + extern int h_errno; +#endif + +#ifndef WITH_NOIO +# ifndef WIN32 +# ifndef PALM +# include +# ifdef VXWORKS +# include +# endif +# ifndef VXWORKS +# ifndef SYMBIAN +# include +# endif +# endif +# ifdef SUN_OS +# include /* SUN */ +# include /* SUN < 2.8 (?) */ +# endif +# ifdef VXWORKS +# include +# else +# include +# endif +# include +# ifdef OS390 +# include +# else +# include /* TCP_NODELAY */ +# endif +# include +# endif +# endif +#endif + +#ifdef WITH_FASTCGI +# include +#endif + +#ifdef WITH_OPENSSL +# define OPENSSL_NO_KRB5 +# include +# include +# include +# ifndef ALLOW_OLD_VERSIONS +# if (OPENSSL_VERSION_NUMBER < 0x00905100L) +# error "Must use OpenSSL 0.9.6 or later" +# endif +# endif +#endif + +#ifdef WITH_GZIP +# ifndef WITH_ZLIB +# define WITH_ZLIB +# endif +#endif + +#ifdef WITH_CASEINSENSITIVETAGS +# define SOAP_STRCMP soap_tag_cmp /* case insensitve XML element/attribute names */ +#else +# define SOAP_STRCMP strcmp /* case sensitive XML element/attribute names */ +#endif + +#ifdef WITH_ZLIB +# include +#endif + +#ifndef PALM +# include /* for isnan() */ +#endif + +/* #define DEBUG */ /* Uncomment to debug sending (in file SENT.log) receiving (in file RECV.log) and messages (in file TEST.log) */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef WIN32 +# ifndef UNDER_CE +# include +# include +# endif +# include +/* # include */ /* Alternative: use winsock2 (not available with eVC) */ +/* WR[ */ +# ifdef WITH_IPV6 +# include +# include +# endif +#else +# ifdef VXWORKS +# include +# include +# include +# endif +/* ]WR */ +# ifndef WITH_NOIO +# ifndef PALM +# include +# include +# include +# include +# endif +# endif +#endif + +#ifdef WIN32 +# define SOAP_SOCKET SOCKET +#else +# define SOAP_SOCKET int +# define closesocket(n) close(n) +#endif + +#define SOAP_INVALID_SOCKET (-1) +#define soap_valid_socket(n) ((n) != SOAP_INVALID_SOCKET) + +#if defined(SYMBIAN) +# define LONG64 long +# define ULONG64 unsigned LONG64 +#elif !defined(WIN32) || defined(__GLIBC__) || defined(__GNU__) +# ifndef LONG64 +# define LONG64 long long +# define ULONG64 unsigned LONG64 +# endif +#elif defined(UNDER_CE) +# define LONG64 __int64 +# define ULONG64 unsigned LONG64 +#elif defined(__BORLANDC__) +# define LONG64 __int64 +# define ULONG64 unsigned LONG64 +#endif + +#if defined(WIN32) +# define soap_int32 __int32 +#elif defined(SYMBIAN) +# define soap_int32 long +#elif defined(PALM) +# define soap_int32 Int32 +#else +# define soap_int32 int32_t +#endif + +#ifdef WIN32 +# define SOAP_EINTR WSAEINTR +# define SOAP_EAGAIN WSAEWOULDBLOCK +# define SOAP_EWOULDBLOCK WSAEWOULDBLOCK +# define SOAP_EINPROGRESS WSAEINPROGRESS +#else +# define SOAP_EINTR EINTR +# define SOAP_EAGAIN EAGAIN +# ifdef SYMBIAN +# define SOAP_EWOULDBLOCK 9898 +# define SOAP_EINPROGRESS 9899 +# else +# define SOAP_EWOULDBLOCK EWOULDBLOCK +# define SOAP_EINPROGRESS EINPROGRESS +# endif +#endif + +#ifdef WIN32 +# ifdef UNDER_CE +# define soap_errno GetLastError() +# define soap_socket_errno GetLastError() +# else +# define soap_errno GetLastError() +# define soap_socket_errno WSAGetLastError() +# endif +#else +# ifndef WITH_NOIO +# define soap_errno errno +# define soap_socket_errno errno +# else +# define soap_errno 0 +# define soap_socket_errno 0 +# endif +#endif + +#ifndef SOAP_BUFLEN +# ifndef WITH_LEAN +# define SOAP_BUFLEN (32768) /* buffer length for socket packets, also used by gethostbyname_r so don't make this too small */ +# else +# define SOAP_BUFLEN (2048) +# endif +#endif +#ifndef SOAP_LABLEN +# ifndef WITH_LEAN +# define SOAP_LABLEN (256) /* initial look-aside buffer length */ +# else +# define SOAP_LABLEN (32) +# endif +#endif +#ifndef SOAP_PTRHASH +# ifndef WITH_LEAN +# define SOAP_PTRHASH (1024) /* size of pointer analysis hash table (must be power of 2) */ +# else +# define SOAP_PTRHASH (16) +# endif +#endif +#ifndef SOAP_IDHASH +# ifndef WITH_LEAN +# define SOAP_IDHASH (1999) /* prime size of hash table for parsed id/ref */ +# else +# define SOAP_IDHASH (19) /* 19, 199 */ +# endif +#endif +#ifndef SOAP_BLKLEN +# ifndef WITH_LEAN +# define SOAP_BLKLEN (256) /* size of blocks to collect long strings and XML attributes */ +# else +# define SOAP_BLKLEN (32) +# endif +#endif +#ifndef SOAP_TAGLEN +# ifndef WITH_LEAN +# define SOAP_TAGLEN (256) /* maximum length of XML element tag/attribute name or host/path name + 1 */ +# else +# define SOAP_TAGLEN (64) +# endif +#endif +#ifndef SOAP_HDRLEN +# ifndef WITH_LEAN +# define SOAP_HDRLEN (8192) /* maximum length of HTTP header line (must be >4096 to read cookies) */ +# else +# define SOAP_HDRLEN (1024) +# endif +#endif +#ifndef SOAP_MAXDIMS +# ifndef WITH_LEAN +# define SOAP_MAXDIMS (16) /* maximum array dimensions (array nestings) must be less than 64 to protect soap->tmpbuf */ +# else +# define SOAP_MAXDIMS (4) +# endif +#endif + +#ifndef SOAP_MAXLOGS +# define SOAP_MAXLOGS (3) /* max number of debug logs per struct soap environment */ +# define SOAP_INDEX_RECV (0) +# define SOAP_INDEX_SENT (1) +# define SOAP_INDEX_TEST (2) +#endif + +#ifndef SOAP_MAXKEEPALIVE +# define SOAP_MAXKEEPALIVE (100) /* max iterations to keep server connection alive */ +#endif + +#ifndef SOAP_MAXARRAYSIZE +# define SOAP_MAXARRAYSIZE (100000) /* "trusted" max size of inbound SOAP array for compound array allocation */ +#endif + +#ifdef VXWORKS +# ifdef __INCmathh +# include +# ifndef HAVE_ISNAN +# define HAVE_ISNAN +# endif +# define soap_isnan(num) isNan(num) +# endif +#endif + +#ifdef WIN32 +# include +# ifndef HAVE_ISNAN +# define HAVE_ISNAN +# endif +# define soap_isnan(num) _isnan(num) +#endif + +#ifdef SUN_OS +# define soap_isnan(n) isnan(n) +#endif + +#if !defined(HAVE_ISNAN) && (defined(_MATH_H) || defined(_MATH_INCLUDED)) +# define HAVE_ISNAN +#endif + +#ifndef soap_isnan +# ifdef HAVE_ISNAN +# define soap_isnan(n) isnan(n) +# else +# define soap_isnan(_) (0) +# endif +#endif + +extern const struct soap_double_nan { unsigned int n1, n2; } soap_double_nan; + +#ifdef VXWORKS +# ifndef FLT_MAX +# define FLT_MAX _ARCH_FLT_MAX +# endif +# ifndef DBL_MAX +# define DBL_MAX _ARCH_DBL_MAX +# endif +#endif + +#ifndef FLT_NAN +# ifdef HAVE_ISNAN +# define FLT_NAN (*(float*)&soap_double_nan) +# else +# define FLT_NAN (0.0) +# endif +#endif + +#ifndef FLT_PINFTY +# ifdef FLT_MAX +# define FLT_PINFTY FLT_MAX +# else +# ifdef HUGE_VAL +# define FLT_PINFTY (float)HUGE_VAL +# else +# ifdef FLOAT_MAX +# define FLT_PINFTY FLOAT_MAX +# else +# define FLT_PINFTY (3.40282347e+38F) +# endif +# endif +# endif +#endif + +#ifndef FLT_NINFTY +# define FLT_NINFTY (-FLT_PINFTY) +#endif + +#ifndef DBL_NAN +# ifdef HAVE_ISNAN +# define DBL_NAN (*(double*)&soap_double_nan) +# else +# define DBL_NAN (0.0) +# endif +#endif + +#ifndef DBL_PINFTY +# ifdef DBL_MAX +# define DBL_PINFTY DBL_MAX +# else +# ifdef HUGE_VAL +# define DBL_PINFTY (double)HUGE_VAL +# else +# ifdef DOUBLE_MAX +# define DBL_PINFTY DOUBLE_MAX +# else +# define DBL_PINFTY (1.7976931348623157e+308) +# endif +# endif +# endif +#endif + +#ifndef DBL_NINFTY +# define DBL_NINFTY (-DBL_PINFTY) +#endif + +#define soap_ispinfd(n) ((n) >= DBL_PINFTY) +#define soap_ispinff(n) ((n) >= FLT_PINFTY) +#define soap_isninfd(n) ((n) <= DBL_NINFTY) +#define soap_isninff(n) ((n) <= FLT_NINFTY) + +/* gSOAP error codes */ + +#define SOAP_EOF EOF +#define SOAP_ERR EOF +#define SOAP_OK 0 +#define SOAP_CLI_FAULT 1 +#define SOAP_SVR_FAULT 2 +#define SOAP_TAG_MISMATCH 3 +#define SOAP_TYPE 4 +#define SOAP_SYNTAX_ERROR 5 +#define SOAP_NO_TAG 6 +#define SOAP_IOB 7 +#define SOAP_MUSTUNDERSTAND 8 +#define SOAP_NAMESPACE 9 +/* #define SOAP_OBJ_MISMATCH 10 obsolete */ +#define SOAP_FATAL_ERROR 11 +#define SOAP_FAULT 12 +#define SOAP_NO_METHOD 13 +#define SOAP_GET_METHOD 14 +#define SOAP_EOM 15 +#define SOAP_NULL 16 +#define SOAP_MULTI_ID 17 +#define SOAP_MISSING_ID 18 +#define SOAP_HREF 19 +#define SOAP_TCP_ERROR 20 +#define SOAP_HTTP_ERROR 21 +#define SOAP_SSL_ERROR 22 +#define SOAP_ZLIB_ERROR 23 +#define SOAP_DIME_ERROR 24 +#define SOAP_DIME_HREF 25 +#define SOAP_DIME_MISMATCH 26 +#define SOAP_DIME_END 27 +#define SOAP_MIME_ERROR 28 +#define SOAP_VERSIONMISMATCH 29 +#define SOAP_PLUGIN_ERROR 30 +#define SOAP_DATAENCODINGUNKNOWN 31 +#define SOAP_REQUIRED 32 +#define SOAP_PROHIBITED 33 +#define SOAP_OCCURS 34 +#define SOAP_LENGTH 35 + +#define soap_xml_error_check(e) ((e) == SOAP_TAG_MISMATCH || (e) == SOAP_TAG_END || (e) == SOAP_SYNTAX_ERROR || (e) == SOAP_NAMESPACE || (e) == SOAP_MULTI_ID || (e) == SOAP_MISSING_ID || (e) == SOAP_REQUIRED || (e) == SOAP_PROHIBITED || (e) == SOAP_OCCURS || (e) == SOAP_LENGTH || (e) == SOAP_NULL || (e) == SOAP_HREF) +#define soap_soap_error_check(e) ((e) == SOAP_CLI_FAULT || (e) == SOAP_SVR_FAULT || (e) == SOAP_VERSIONMISMATCH || (e) == SOAP_MUSTUNDERSTAND || (e) == SOAP_FAULT || (e) == SOAP_NO_METHOD) +#define soap_tcp_error_check(e) ((e) == SOAP_EOF || (e) == SOAP_TCP_ERROR) +#define soap_ssl_error_check(e) ((e) == SOAP_SSL_ERROR) +#define soap_zlib_error_check(e) ((e) == SOAP_ZLIB_ERROR) +#define soap_mime_error_check(e) ((e) == SOAP_MIME_ERROR) +#define soap_dime_error_check(e) ((e) == SOAP_DIME_ERROR || (e) == SOAP_DIME_MISMATCH) +#define soap_http_error_check(e) ((e) == SOAP_HTTP_ERROR || (e) == SOAP_GET_METHOD || ((e) >= 100 && (e) < 600)) + +/* gSOAP HTTP response status codes 100 to 600 are reserved */ + +/* Special gSOAP HTTP response status codes */ + +#define SOAP_STOP 1000 /* No HTTP response */ +#define SOAP_HTML 1001 /* Custom HTML response */ +#define SOAP_FILE 1002 /* Custom file-based response */ + +/* gSOAP HTTP request status codes */ + +#define SOAP_POST 1003 +#define SOAP_GET 1104 + +/* gSOAP DIME */ + +#define SOAP_DIME_CF 0x01 +#define SOAP_DIME_ME 0x02 +#define SOAP_DIME_MB 0x04 +#define SOAP_DIME_VERSION 0x08 /* DIME version 1 */ +#define SOAP_DIME_MEDIA 0x10 +#define SOAP_DIME_ABSURI 0x20 + +/* gSOAP ZLIB */ + +#define SOAP_ZLIB_NONE 0x00 +#define SOAP_ZLIB_DEFLATE 0x01 +#define SOAP_ZLIB_INFLATE 0x02 +#define SOAP_ZLIB_GZIP 0x02 + +/* gSOAP transport, connection, and content encoding modes */ + +typedef soap_int32 soap_mode; + +#define SOAP_IO 0x00000003 /* IO mask */ +#define SOAP_IO_FLUSH 0x00000000 /* flush output immediately, no buffering */ +#define SOAP_IO_BUFFER 0x00000001 /* buffer output in packets of size SOAP_BUFLEN */ +#define SOAP_IO_STORE 0x00000002 /* store entire output to determine length for transport */ +#define SOAP_IO_CHUNK 0x00000003 /* use HTTP chunked transfer AND buffer packets */ + +#define SOAP_IO_LENGTH 0x00000004 +#define SOAP_IO_KEEPALIVE 0x00000008 + +#define SOAP_ENC_LATIN 0x00800010 /* iso-8859-1 encoding */ +#define SOAP_ENC_XML 0x00000020 /* plain XML encoding, no HTTP header */ +#define SOAP_ENC_DIME 0x00000040 +#define SOAP_ENC_MIME 0x00000080 +#define SOAP_ENC_ZLIB 0x00000100 +#define SOAP_ENC_SSL 0x00000200 + +#define SOAP_ENC 0x00000FFF /* IO and ENC mask */ + +#define SOAP_XML_STRICT 0x00001000 /* strict validation */ +#define SOAP_XML_CANONICAL 0x00002000 /* C14N canonical XML */ +#define SOAP_XML_TREE 0x00004000 +#define SOAP_XML_GRAPH 0x00008000 +#define SOAP_XML_NIL 0x00010000 +#define SOAP_XML_DOM 0x00020000 +#define SOAP_XML_SEC 0x00040000 /* reserved for WS security */ + +#define SOAP_C_NOIOB 0x00100000 +#define SOAP_C_UTFSTRING 0x00200000 +#define SOAP_C_MBSTRING 0x00400000 + +#define SOAP_DOM_TREE 0x01000000 +#define SOAP_DOM_NODE 0x02000000 + +#define SOAP_IO_DEFAULT SOAP_IO_FLUSH + +/* SSL client/server authentication settings */ + +#define SOAP_SSL_NO_AUTHENTICATION 0x00 /* for testing purposes */ +#define SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION 0x01 /* client requires server to authenticate */ +#define SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION 0x02 /* server requires client to authenticate */ + +#define SOAP_SSL_DEFAULT SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION + +/* */ + +#define SOAP_BEGIN 0 +#define SOAP_IN_ENVELOPE 2 +#define SOAP_IN_HEADER 3 +#define SOAP_END_HEADER 4 +#define SOAP_IN_BODY 5 +#define SOAP_END_BODY 6 +#define SOAP_END_ENVELOPE 7 +#define SOAP_END 8 + +/* DEBUG macros */ + +#ifndef WITH_LEAN +# ifdef DEBUG +# ifndef SOAP_DEBUG +# define SOAP_DEBUG +# endif +# endif +#endif + +#ifdef SOAP_DEBUG +# ifndef SOAP_MESSAGE +# define SOAP_MESSAGE fprintf +# endif +# ifndef DBGLOG +# define DBGLOG(DBGFILE, CMD) \ +{ if (soap)\ + { if (!soap->fdebug[SOAP_INDEX_##DBGFILE])\ + soap_open_logfile(soap, SOAP_INDEX_##DBGFILE);\ + if (soap->fdebug[SOAP_INDEX_##DBGFILE])\ + { FILE *fdebug = soap->fdebug[SOAP_INDEX_##DBGFILE];\ + CMD;\ + fflush(fdebug);\ + }\ + }\ +} +# endif +# ifndef DBGMSG +# define DBGMSG(DBGFILE, MSG, LEN) \ +{ if (soap)\ + { if (!soap->fdebug[SOAP_INDEX_##DBGFILE])\ + soap_open_logfile(soap, SOAP_INDEX_##DBGFILE);\ + if (soap->fdebug[SOAP_INDEX_##DBGFILE])\ + { fwrite((MSG), 1, (LEN), soap->fdebug[SOAP_INDEX_##DBGFILE]);\ + fflush(soap->fdebug[SOAP_INDEX_##DBGFILE]);\ + }\ + }\ +} +# endif +#else +# define DBGLOG(DBGFILE, CMD) +# define DBGMSG(DBGFILE, MSG, LEN) +#endif + +/* UCS-4 requires 32 bits (0-7FFFFFFF, the sign bit is used by gSOAP to distinguish XML entities) */ +typedef soap_int32 soap_wchar; + +struct Namespace +{ const char *id; + const char *ns; + const char *in; + char *out; +}; + +struct soap_nlist +{ struct soap_nlist *next; + unsigned int level; + short index; /* corresponding entry in ns mapping table */ + char *ns; /* only set when parsed ns URI is not in the ns mapping table */ + char id[1]; /* the actual string value flows into the allocated region below this struct */ +}; + +struct soap_blist +{ struct soap_blist *next; + char *ptr; + size_t size; +}; + +struct soap_array +{ void *__ptr; + int __size; +}; + +/* pointer serialization management */ +struct soap_plist +{ struct soap_plist *next; + const void *ptr; + const struct soap_array *array; + int type; + int id; + char mark1; + char mark2; +}; + +/* class allocation list */ +struct soap_clist +{ struct soap_clist *next; + void *ptr; + int type; + int size; + void (*fdelete)(struct soap_clist*); +}; + +struct soap_attribute +{ struct soap_attribute *next; + char *value; + size_t size; + char *ns; + short visible; + char name[1]; /* the actual name string flows into the allocated region below this struct */ +}; + +struct soap_cookie +{ struct soap_cookie *next; + char *name; + char *value; + char *domain; + char *path; + long expire; /* client-side: local time to expire; server-side: seconds to expire */ + unsigned int version; + short secure; + short session; /* server-side */ + short env; /* server-side: got cookie from client */ + short modified; /* server-side: client cookie was modified */ +}; + +#ifdef __cplusplus +SOAP_FMAC1 struct soap_multipart* SOAP_FMAC2 soap_next_multipart(struct soap_multipart*); + +class soap_multipart_iterator +{ public: + struct soap_multipart *content; + bool operator==(const soap_multipart_iterator& iter) const + { return content == iter.content; } + bool operator!=(const soap_multipart_iterator& iter) const + { return content != iter.content; } + struct soap_multipart &operator*() const + { return *content; } + soap_multipart_iterator &operator++() + { content = soap_next_multipart(content); return *this; } + soap_multipart_iterator() : content(NULL) + { } + soap_multipart_iterator(struct soap_multipart *p) : content(p) + { } +}; +#endif + +#ifndef WITH_LEANER +struct soap_dime +{ size_t count; + size_t size; + size_t chunksize; + size_t buflen; + char flags; + char *ptr; + const char *id; + const char *type; + const char *options; + struct soap_multipart *list; /* list of DIME attachments received */ + struct soap_multipart *first, *last; /* temporary in/out queue */ +#ifdef __cplusplus + soap_multipart_iterator begin() + { soap_multipart_iterator iter(list); return iter; }; + soap_multipart_iterator end() + { soap_multipart_iterator iter(NULL); return iter; }; +#endif +}; +#endif + +#ifndef WITH_LEANER +struct soap_mime +{ char *boundary; /* MIME boundary */ + const char *start; /* MIME start ID */ + struct soap_multipart *list; /* list of DIME attachments received */ + struct soap_multipart *first, *last; /* temporary in/out queue */ +#ifdef __cplusplus + soap_multipart_iterator begin() + { soap_multipart_iterator iter(list); return iter; }; + soap_multipart_iterator end() + { soap_multipart_iterator iter(NULL); return iter; }; +#endif +}; +#endif + +#ifndef WITH_LEANER +/* RFC2045 MIME content transfer encodings */ +enum soap_mime_encoding +{ SOAP_MIME_NONE, + SOAP_MIME_7BIT, + SOAP_MIME_8BIT, + SOAP_MIME_BINARY, + SOAP_MIME_QUOTED_PRINTABLE, + SOAP_MIME_BASE64, + SOAP_MIME_IETF_TOKEN, + SOAP_MIME_X_TOKEN +}; +#endif + +#ifndef WITH_LEANER +/* DIME/MIME multipart list */ +struct soap_multipart +{ struct soap_multipart *next; + char *ptr; /* points to raw data content */ + size_t size; /* size of data content */ + const char *id; /* DIME/MIME content ID */ + const char *type; /* DIME/MIME type (MIME type format) */ + const char *options; /* DIME options */ + enum soap_mime_encoding encoding; /* MIME Content-Transfer-Encoding */ + const char *location; /* MIME Content-Location (optional) */ + const char *description; /* MIME Content-Description (optional) */ +#ifdef __cplusplus + typedef soap_multipart_iterator iterator; +#endif +}; +#endif + +#ifndef WITH_LEANER +struct soap_dom_attribute +{ struct soap_dom_attribute *next; + const char *nstr; + char *name; + char *data; + wchar_t *wide; + struct soap *soap; +#ifdef __cplusplus + struct soap_dom_attribute &set(const char *nstr, const char *name); /* set namespace and name */ + struct soap_dom_attribute &set(const char *data); /* set data */ + void unlink(); + soap_dom_attribute(); + soap_dom_attribute(struct soap *soap); + soap_dom_attribute(struct soap *soap, const char *nstr, const char *name, const char *data); + ~soap_dom_attribute(); +#endif +}; +#endif + +#ifndef WITH_LEANER +#ifdef __cplusplus +class soap_dom_iterator +{ public: + struct soap_dom_element *elt; + const char *nstr; + const char *name; + int type; + bool operator==(const soap_dom_iterator&) const; + bool operator!=(const soap_dom_iterator&) const; + struct soap_dom_element &operator*() const; + soap_dom_iterator &operator++(); + soap_dom_iterator(); + soap_dom_iterator(struct soap_dom_element*); + ~soap_dom_iterator(); +}; +#endif +#endif + +#ifndef WITH_LEANER +struct soap_dom_element +{ struct soap_dom_element *next; /* next sibling */ + struct soap_dom_element *prnt; /* parent */ + struct soap_dom_element *elts; /* first child element */ + struct soap_dom_attribute *atts; /* first child attribute */ + const char *nstr; /* namespace string */ + char *name; /* element tag name */ + char *data; /* element content data (with SOAP_C_UTFSTRING flag set) */ + wchar_t *wide; /* element content data */ + int type; /* optional: serialized C/C++ data type */ + void *node; /* optional: pointer to serialized C/C++ data */ + struct soap *soap; +#ifdef __cplusplus + typedef soap_dom_iterator iterator; + struct soap_dom_element &set(const char *nstr, const char *name); + struct soap_dom_element &set(const char *data); + struct soap_dom_element &set(void *node, int type); + struct soap_dom_element &add(struct soap_dom_element*); + struct soap_dom_element &add(struct soap_dom_element&); + struct soap_dom_element &add(struct soap_dom_attribute*); + struct soap_dom_element &add(struct soap_dom_attribute&); + soap_dom_iterator begin(); + soap_dom_iterator end(); + soap_dom_iterator find(const char *nstr, const char *name); + soap_dom_iterator find(int type); + void unlink(); + soap_dom_element(); + soap_dom_element(struct soap *soap); + soap_dom_element(struct soap *soap, const char *nstr, const char *name); + soap_dom_element(struct soap *soap, const char *nstr, const char *name, const char *data); + soap_dom_element(struct soap *soap, const char *nstr, const char *name, void *node, int type); + ~soap_dom_element(); +#endif +}; +#endif + +#if defined(__cplusplus) && !defined(WITH_LEAN) +} +extern ostream &operator<<(ostream&, const struct soap_dom_element&); +extern istream &operator>>(istream&, struct soap_dom_element&); +extern "C" { +#endif + +struct soap +{ short version; /* 1 = SOAP1.1 and 2 = SOAP1.2 (set automatically from namespace URI in nsmap table) */ + short copy; /* 1 = copy of another soap struct */ + soap_mode mode; + soap_mode imode; + soap_mode omode; + const char *float_format; /* points to user-definable format string for floats (<1024 chars) */ + const char *double_format; /* points to user-definable format string for doubles (<1024 chars) */ + const char *dime_id_format; /* points to user-definable format string for integer DIME id ( 0, gives socket recv timeout in seconds, < 0 in usec */ + int send_timeout; /* when > 0, gives socket send timeout in seconds, < 0 in usec */ + int connect_timeout; /* when > 0, gives socket connect() timeout in seconds, < 0 in usec */ + int accept_timeout; /* when > 0, gives socket accept() timeout in seconds, < 0 in usec */ + int socket_flags; /* socket recv() and send() flags, e.g. set to MSG_NOSIGNAL to disable sigpipe */ + int connect_flags; /* connect() SOL_SOCKET sockopt flags, e.g. set to SO_DEBUG to debug socket */ + int bind_flags; /* bind() SOL_SOCKET sockopt flags, e.g. set to SO_REUSEADDR to enable reuse */ + int accept_flags; /* accept() SOL_SOCKET sockopt flags */ + const struct Namespace *namespaces; /* Pointer to global namespace mapping table */ + struct Namespace *local_namespaces; /* Local namespace mapping table */ + struct soap_nlist *nlist; /* namespace stack */ + struct soap_blist *blist; /* block allocation stack */ + struct soap_clist *clist; /* class instance allocation list */ + void *alist; /* memory allocation list */ + struct soap_ilist *iht[SOAP_IDHASH]; + struct soap_plist *pht[SOAP_PTRHASH]; + struct SOAP_ENV__Header *header; + struct SOAP_ENV__Fault *fault; + void *user; /* to pass user-defined data */ + struct soap_plugin *plugins; /* linked list of plug-in data */ + char *userid; /* HTTP Basic authorization userid */ + char *passwd; /* HTTP Basic authorization passwd */ + int (*fpost)(struct soap*, const char*, const char*, int, const char*, const char*, size_t); + int (*fget)(struct soap*); + int (*fposthdr)(struct soap*, const char*, const char*); + int (*fresponse)(struct soap*, int, size_t); + int (*fparse)(struct soap*); + int (*fparsehdr)(struct soap*, const char*, const char*); + int (*fresolve)(struct soap*, const char*, struct in_addr* inaddr); + int (*fconnect)(struct soap*, const char*, const char*, int); + int (*fdisconnect)(struct soap*); + int (*fclosesocket)(struct soap*, SOAP_SOCKET); + int (*fshutdownsocket)(struct soap*, SOAP_SOCKET, int); + int (*fopen)(struct soap*, const char*, const char*, int); + int (*faccept)(struct soap*, int, struct sockaddr*, int *n); + int (*fclose)(struct soap*); + int (*fsend)(struct soap*, const char*, size_t); + size_t (*frecv)(struct soap*, char*, size_t); + int (*fpoll)(struct soap*); + int (*fignore)(struct soap*, const char*); + int (*fserveloop)(struct soap*); + void *(*fplugin)(struct soap*, const char*); +#ifndef WITH_LEANER + int (*fprepareinit)(struct soap*); + int (*fpreparesend)(struct soap*, const char*, size_t); + int (*fpreparerecv)(struct soap*, const char*, size_t); + void *(*fdimereadopen)(struct soap*, void*, const char*, const char*, const char*); + void *(*fdimewriteopen)(struct soap*, const char*, const char*, const char*); + void (*fdimereadclose)(struct soap*, void*); + void (*fdimewriteclose)(struct soap*, void*); + size_t (*fdimeread)(struct soap*, void*, char*, size_t); + int (*fdimewrite)(struct soap*, void*, const char*, size_t); +#endif + int master; + int socket; +#if defined(__cplusplus) && !defined(WITH_LEAN) + ostream *os; + istream *is; +#else + void *os; /* preserve alignment */ + void *is; /* preserve alignment */ +#endif +#ifndef UNDER_CE + int sendfd; + int recvfd; +#else + FILE *sendfd; + FILE *recvfd; +#endif +#ifdef WIN32 + char errorstr[256]; /* buf for FormatMessage() */ +#endif + size_t bufidx; /* index in soap.buf[] */ + size_t buflen; /* length of soap.buf[] content */ + soap_wchar ahead; /* parser lookahead */ + short cdata; /* CDATA parser state */ + short body; + unsigned int level; /* XML nesting level */ + size_t count; /* message length counter */ + size_t length; /* message length as set by HTTP header */ +#ifdef WITH_FAST + char *labbuf; /* look-aside buffer */ + size_t lablen; /* look-aside buffer allocated length */ + size_t labidx; /* look-aside buffer index to available part */ +#endif + char buf[SOAP_BUFLEN];/* send and receive buffer */ + char tmpbuf[1024]; /* in/output buffer for HTTP headers, simpleType values, attribute names, and DIME >=1024 bytes */ + char msgbuf[1024]; /* output buffer for (error) messages <=1024 bytes */ + char tag[SOAP_TAGLEN]; + char id[SOAP_TAGLEN]; + char href[SOAP_TAGLEN]; + char type[SOAP_TAGLEN]; + char arrayType[SOAP_TAGLEN]; + char arraySize[SOAP_TAGLEN]; + char arrayOffset[SOAP_TAGLEN]; + short other; + short root; + short position; + int positions[SOAP_MAXDIMS]; + struct soap_attribute *attributes; /* attribute list */ + short encoding; + short mustUnderstand; + short null; + short ns; + short part; + short alloced; + short peeked; + short keep_alive; + size_t chunksize; + size_t chunkbuflen; + char endpoint[SOAP_TAGLEN]; + char path[SOAP_TAGLEN]; + char host[SOAP_TAGLEN]; + char *action; + char *authrealm; /* HTTP authentication realm */ + char *prolog; /* XML declaration prolog */ + int port; + unsigned int max_keep_alive; + const char *proxy_host; /* Proxy Server host name */ + int proxy_port; /* Proxy Server port (default = 8080) */ + const char *proxy_userid; /* Proxy Authorization user name */ + const char *proxy_passwd; /* Proxy Authorization password */ + int status; /* -1 when request, else error code to be returned by server */ + int error; + int errmode; + int errnum; + unsigned long idnum; + unsigned long ip; +#ifndef WITH_LEANER + struct soap_dom_element *dom; + struct soap_dime dime; + struct soap_mime mime; +#endif +#if !defined(WITH_LEAN) || defined(SOAP_DEBUG) + const char *logfile[SOAP_MAXLOGS]; + FILE *fdebug[SOAP_MAXLOGS]; +#endif +#ifndef WITH_LEAN + struct soap_cookie *cookies; + const char *cookie_domain; + const char *cookie_path; + int cookie_max; +#endif +#ifdef WITH_OPENSSL + int (*fsslauth)(struct soap*); + int (*fsslverify)(int, X509_STORE_CTX*); + BIO *bio; + SSL *ssl; + SSL_CTX *ctx; + short require_server_auth; + short require_client_auth; + short rsa; /* when set, use RSA instead of DH */ + const char *keyfile; + const char *password; + const char *dhfile; + const char *cafile; + const char *capath; + const char *randfile; + SSL_SESSION *session; + char session_host[SOAP_TAGLEN]; + int session_port; +#endif +#ifdef WITH_ZLIB + short zlib_state; /* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_INFLATE */ + short zlib_in; /* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_GZIP */ + short zlib_out; /* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_GZIP */ + z_stream d_stream; /* decompression stream */ + char z_buf[SOAP_BUFLEN]; /* buffer */ + size_t z_buflen; + unsigned short z_level; /* compression level to be used (0=none, 1=fast to 9=best) */ + uLong z_crc; /* internal gzip crc */ + float z_ratio_in; /* detected compression ratio compressed_length/length of inbound message */ + float z_ratio_out; /* detected compression ratio compressed_length/length of outbound message */ +#endif +/* WR[ */ +#ifdef WMW_RPM_IO + void *rpmreqid; +#endif /* WMW_RPM_IO */ +/* ]WR */ +}; + +struct soap_code_map +{ long code; + const char *string; +}; + +/* forwarding list */ +struct soap_flist +{ struct soap_flist *next; + int type; + void *ptr; + unsigned int level; + void (*fcopy)(struct soap*, int, int, void*, const void*, size_t); +}; + +/* id-ref forwarding list */ +struct soap_ilist +{ struct soap_ilist *next; + int type; + size_t size; + void *link; + void *copy; + struct soap_flist *flist; + void *ptr; + unsigned int level; + char id[1]; /* the actual id string value flows into the allocated region below this struct */ +}; + +struct soap_plugin +{ struct soap_plugin *next; + const char *id; + void *data; + int (*fcopy)(struct soap *soap, struct soap_plugin *dst, struct soap_plugin *src); + void (*fdelete)(struct soap *soap, struct soap_plugin *p); /* should delete fields of plugin only and not free(p) */ +}; + +#ifndef WITH_NONAMESPACES +extern SOAP_NMAC struct Namespace namespaces[]; +#endif + +#ifndef WITH_LEAN +# define soap_get0(soap) (((soap)->bufidx>=(soap)->buflen && soap_recv(soap)) ? EOF : (unsigned char)(soap)->buf[(soap)->bufidx]) +# define soap_get1(soap) (((soap)->bufidx>=(soap)->buflen && soap_recv(soap)) ? EOF : (unsigned char)(soap)->buf[(soap)->bufidx++]) +#else +soap_wchar soap_get0(struct soap*); +soap_wchar soap_get1(struct soap*); +#endif + +#define soap_revget1(soap) ((soap)->bufidx--) +#define soap_unget(soap, c) ((soap)->ahead = c) +#define soap_register_plugin(soap, plugin) soap_register_plugin_arg(soap, plugin, NULL) +#define soap_imode(soap, n) ((soap)->mode = (soap)->imode = (n)) +#define soap_set_imode(soap, n) ((soap)->mode = (soap)->imode |= (n)) +#define soap_clr_imode(soap, n) ((soap)->mode = (soap)->imode &= ~(n)) +#define soap_omode(soap, n) ((soap)->mode = (soap)->omode = (n)) +#define soap_set_omode(soap, n) ((soap)->mode = (soap)->omode |= (n)) +#define soap_clr_omode(soap, n) ((soap)->mode = (soap)->omode &= ~(n)) +#define soap_destroy(soap) soap_delete((soap), NULL) + +#ifdef HAVE_STRRCHR +# define soap_strrchr(s, t) strrchr(s, t) +#else + SOAP_FMAC1 char* SOAP_FMAC2 soap_strrchr(const char *s, int t); +#endif + +#ifdef HAVE_STRTOL +# define soap_strtol(s, t, b) strtol(s, t, b) +#else + SOAP_FMAC1 long SOAP_FMAC2 soap_strtol(const char *s, char **t, int b); +#endif + +#ifdef HAVE_STRTOUL +# define soap_strtoul(s, t, b) strtoul(s, t, b) +#else + SOAP_FMAC1 unsigned long SOAP_FMAC2 soap_strtoul(const char *s, char **t, int b); +#endif + +#ifdef WITH_NOIDREF +# define soap_embedded(s, p, t) (0) +# define soap_id_lookup(s, i, p, t, n, k) (p) +# define soap_id_forward(s, h, p, st, tt, n, k, fc) (p) +# define soap_reference(s, a, t) (1) +# define soap_array_reference(s, p, a, n, t) (1) +# define soap_embed(s, p, a, n, t, pp) (0) +# define soap_embedded_id(s, i, p, t) (i) +# define soap_is_embedded(s, p) (0) +# define soap_is_single(s, p) (1) +# define soap_lookup_type(s, i) (0) +# define soap_getindependent(s) (0) +# define soap_putindependent(s) (0) +# define soap_getelement(s, n) (0) +# define soap_putelement(s, p, t, i, n) (0) +# define soap_markelement(s, p, n) (0) +#endif + +SOAP_FMAC1 void SOAP_FMAC2 soap_fault(struct soap*); +SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultcode(struct soap*); +SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultstring(struct soap*); +SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultdetail(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_serializeheader(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putheader(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getheader(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_serializefault(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putfault(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getfault(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_poll(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_connect_command(struct soap*, int, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_connect(struct soap*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_bind(struct soap*, const char*, int, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_accept(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_accept(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_server_context(struct soap*, unsigned short, const char*, const char*, const char*, const char*, const char*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_client_context(struct soap*, unsigned short, const char*, const char*, const char*, const char*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_puthttphdr(struct soap*, int status, size_t count); + +SOAP_FMAC1 const char* SOAP_FMAC2 soap_get_header_attribute(struct soap*, const char*, const char*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_decode_key(char*, size_t, const char*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_decode_val(char*, size_t, const char*); + +SOAP_FMAC1 size_t SOAP_FMAC2 soap_hash(const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_endpoint(struct soap*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_flush_raw(struct soap*, const char*, size_t); +SOAP_FMAC1 int SOAP_FMAC2 soap_flush(struct soap*); +SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_get(struct soap*); +SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_getchar(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_tag_cmp(const char*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_fault(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_sender_fault(struct soap*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_receiver_fault(struct soap*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_sender_error(struct soap*, const char*, const char*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_receiver_error(struct soap*, const char*, const char*, int); + +SOAP_FMAC1 int SOAP_FMAC2 soap_send_raw(struct soap*, const char*, size_t); +SOAP_FMAC1 int SOAP_FMAC2 soap_recv_raw(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_recv(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_send(struct soap*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_send2(struct soap*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_send3(struct soap*, const char*, const char*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_pututf8(struct soap*, unsigned long); +SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_getutf8(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_putbase64(struct soap*, const unsigned char*, int); +SOAP_FMAC1 unsigned char* SOAP_FMAC2 soap_getbase64(struct soap*, int*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_puthex(struct soap*, const unsigned char*, int); +SOAP_FMAC1 unsigned char* SOAP_FMAC2 soap_gethex(struct soap*, int*); + + +#ifndef WITH_NOIDREF +SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_lookup_id(struct soap*, void *p, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_lookup(struct soap*, const void *p, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_enter(struct soap*, const void *p, const struct soap_array *a, int n, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_array_pointer_lookup(struct soap*, const void *p, const struct soap_array *a, int n, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_embed(struct soap *soap, const void *p, const struct soap_array *a, int n, const char *tag, int type); +SOAP_FMAC1 struct soap_ilist* SOAP_FMAC2 soap_lookup(struct soap*, const char*); +SOAP_FMAC1 struct soap_ilist* SOAP_FMAC2 soap_enter(struct soap*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_resolve(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_embedded(struct soap*, const void *p, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_reference(struct soap*, const void *p, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_array_reference(struct soap*, const void *p, const struct soap_array *a, int n, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_embedded_id(struct soap*, int id, const void *p, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_is_embedded(struct soap*, struct soap_plist*); +SOAP_FMAC1 int SOAP_FMAC2 soap_is_single(struct soap*, struct soap_plist*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_embedded(struct soap*, struct soap_plist*); +#endif + +SOAP_FMAC1 void SOAP_FMAC2 soap_begin_count(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_begin_send(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_end_send(struct soap*); + +SOAP_FMAC1 const struct soap_code_map* SOAP_FMAC2 soap_code(const struct soap_code_map*, const char *str); +SOAP_FMAC1 long SOAP_FMAC2 soap_int_code(const struct soap_code_map*, const char *str, long other); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_str_code(const struct soap_code_map*, long code); + +SOAP_FMAC1 int SOAP_FMAC2 soap_getline(struct soap*, char*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_begin_recv(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_end_recv(struct soap*); + +SOAP_FMAC1 void* SOAP_FMAC2 soap_malloc(struct soap*, size_t); +SOAP_FMAC1 void SOAP_FMAC2 soap_dealloc(struct soap*, void*); +SOAP_FMAC1 struct soap_clist * SOAP_FMAC2 soap_link(struct soap*, void*, int, int, void (*fdelete)(struct soap_clist*)); +SOAP_FMAC1 void SOAP_FMAC2 soap_unlink(struct soap*, const void*); +SOAP_FMAC1 void SOAP_FMAC2 soap_free(struct soap*); + +#ifndef WITH_NOIDREF +SOAP_FMAC1 int SOAP_FMAC2 soap_lookup_type(struct soap*, const char *id); +SOAP_FMAC1 void* SOAP_FMAC2 soap_id_lookup(struct soap*, const char *id, void **p, int t, size_t n, unsigned int k); +SOAP_FMAC1 void* SOAP_FMAC2 soap_id_forward(struct soap*, const char *id, void *p, int st, int tt, size_t n, unsigned int k, void(*fcopy)(struct soap*, int, int, void*, const void*, size_t)); +#endif +SOAP_FMAC1 void* SOAP_FMAC2 soap_id_enter(struct soap*, const char *id, void *p, int t, size_t n, unsigned int k, const char *type, const char *arrayType, void *(*finstantiate)(struct soap*, int, const char*, const char*, size_t*)); +SOAP_FMAC1 void SOAP_FMAC2 soap_fcopy(struct soap *soap, int st, int tt, void *p, const void *q, size_t n); + +SOAP_FMAC1 int SOAP_FMAC2 soap_size(const int *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_getoffsets(const char *, const int *, int *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_getsize(const char *, const char *, int *); +SOAP_FMAC1 int SOAP_FMAC2 soap_getsizes(const char *, int *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_getposition(const char *, int *); + +SOAP_FMAC1 char* SOAP_FMAC2 soap_putsize(struct soap*, const char *, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_putsizesoffsets(struct soap*, const char *, const int *, const int *, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_putsizes(struct soap*, const char *, const int *, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_putoffset(struct soap*, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_putoffsets(struct soap*, const int *, int); + +SOAP_FMAC1 int SOAP_FMAC2 soap_closesock(struct soap*); + +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_new(void); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_new1(soap_mode); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_new2(soap_mode, soap_mode); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_copy(struct soap*); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_copy_context(struct soap*,struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_init(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_init1(struct soap*, soap_mode); +SOAP_FMAC1 void SOAP_FMAC2 soap_init2(struct soap*, soap_mode, soap_mode); +SOAP_FMAC1 void SOAP_FMAC2 soap_done(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_cleanup(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_begin(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_end(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_delete(struct soap*, void*); + +#ifdef SOAP_DEBUG +SOAP_FMAC1 void SOAP_FMAC2 soap_set_recv_logfile(struct soap*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_sent_logfile(struct soap*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_test_logfile(struct soap*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_close_logfiles(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_open_logfile(struct soap*, int); +#endif + +SOAP_FMAC1 const char* SOAP_FMAC2 soap_value(struct soap*); + +SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_advance(struct soap*); +SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_skip(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_match_tag(struct soap*, const char*, const char *); +SOAP_FMAC1 int SOAP_FMAC2 soap_match_array(struct soap*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_element(struct soap*, const char*, int, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_begin_out(struct soap*, const char *tag, int id, const char *type); +SOAP_FMAC1 int SOAP_FMAC2 soap_array_begin_out(struct soap*, const char *tag, int id, const char *type, const char *offset); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_ref(struct soap*, const char *tag, int id, int href); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_href(struct soap*, const char *tag, int id, const char *ref, const char *val); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_null(struct soap*, const char *tag, int id, const char *type); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_id(struct soap*, const char *tag, int id, const void *p, const struct soap_array *a, int d, const char *type, int n); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_result(struct soap*, const char *tag); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_end_out(struct soap*, const char *tag); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_start_end_out(struct soap*, const char *tag); + +SOAP_FMAC1 int SOAP_FMAC2 soap_attribute(struct soap*, const char*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_element_begin_in(struct soap*, const char *tag, int nillable); + +SOAP_FMAC1 int SOAP_FMAC2 soap_element_end_in(struct soap*, const char *tag); + +SOAP_FMAC1 int SOAP_FMAC2 soap_peek_element(struct soap*); + +SOAP_FMAC1 void SOAP_FMAC2 soap_retry(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_revert(struct soap*); + +SOAP_FMAC1 char* SOAP_FMAC2 soap_strdup(struct soap*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_string_out(struct soap*, const char *s, int flag); +SOAP_FMAC1 char* SOAP_FMAC2 soap_string_in(struct soap*, int, long, long); + +#ifndef WITH_LEANER +SOAP_FMAC1 int SOAP_FMAC2 soap_wstring_out(struct soap*, const wchar_t *s, int flag); +SOAP_FMAC1 wchar_t* SOAP_FMAC2 soap_wstring_in(struct soap*, int, long, long); +#endif + +SOAP_FMAC1 int SOAP_FMAC2 soap_match_namespace(struct soap*, const char *, const char*, int n1, int n2); + +SOAP_FMAC1 int SOAP_FMAC2 soap_set_namespaces(struct soap*, struct Namespace*); + +SOAP_FMAC1 void SOAP_FMAC2 soap_pop_namespace(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_push_namespace(struct soap*, const char *,const char *); + +SOAP_FMAC1 int SOAP_FMAC2 soap_new_block(struct soap*); +SOAP_FMAC1 void* SOAP_FMAC2 soap_push_block(struct soap*, size_t); +SOAP_FMAC1 void SOAP_FMAC2 soap_pop_block(struct soap*); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_size_block(struct soap*, size_t); +SOAP_FMAC1 char* SOAP_FMAC2 soap_first_block(struct soap*); +SOAP_FMAC1 char* SOAP_FMAC2 soap_next_block(struct soap*); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_block_size(struct soap*); +SOAP_FMAC1 char* SOAP_FMAC2 soap_save_block(struct soap*, char*, int); +SOAP_FMAC1 void SOAP_FMAC2 soap_end_block(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_begin_out(struct soap*); +SOAP_FMAC1 int soap_envelope_end_out(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_begin_in(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_end_in(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_body_begin_out(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_body_end_out(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_body_begin_in(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_body_end_in(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_recv_header(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_response(struct soap*, int); + +SOAP_FMAC1 int SOAP_FMAC2 soap_send_empty_response(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_recv_empty_response(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_send_fault(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_recv_fault(struct soap*); + +SOAP_FMAC1 void SOAP_FMAC2 soap_print_fault(struct soap*, FILE*); +SOAP_FMAC1 void SOAP_FMAC2 soap_print_fault_location(struct soap*, FILE*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_s2byte(struct soap*, const char*, char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2short(struct soap*, const char*, short*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2int(struct soap*, const char*, int*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2long(struct soap*, const char*, long*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2LONG64(struct soap*, const char*, LONG64*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2float(struct soap*, const char*, float*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2double(struct soap*, const char*, double*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedByte(struct soap*, const char*, unsigned char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedShort(struct soap*, const char*, unsigned short*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedInt(struct soap*, const char*, unsigned int*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedLong(struct soap*, const char*, unsigned long*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2ULONG64(struct soap*, const char*, ULONG64*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2string(struct soap*, const char*, char**); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2QName(struct soap*, const char*, char**); + +#ifndef WITH_LEAN +SOAP_FMAC1 int SOAP_FMAC2 soap_s2dateTime(struct soap*, const char*, time_t*); +#endif + +SOAP_FMAC1 char* SOAP_FMAC2 soap_s2base64(struct soap*, const unsigned char*, char*, size_t); + +SOAP_FMAC1 const char* SOAP_FMAC2 soap_byte2s(struct soap*, char); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_short2s(struct soap*, short); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_int2s(struct soap*, int); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_long2s(struct soap*, long); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_LONG642s(struct soap*, LONG64); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_float2s(struct soap*, float); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_double2s(struct soap*, double); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedByte2s(struct soap*, unsigned char); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedShort2s(struct soap*, unsigned short); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedInt2s(struct soap*, unsigned int); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedLong2s(struct soap*, unsigned long); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_ULONG642s(struct soap*, ULONG64); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_QName2s(struct soap*, const char*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_base642s(struct soap*, const char*, char*, size_t, size_t*); + +#ifndef WITH_LEAN +SOAP_FMAC1 const char* SOAP_FMAC2 soap_dateTime2s(struct soap*, time_t); +#endif + + +SOAP_FMAC1 int* SOAP_FMAC2 soap_inint(struct soap*, const char *tag, int *p, const char *, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_inbyte(struct soap*, const char *tag, char *p, const char *, int); +SOAP_FMAC1 long* SOAP_FMAC2 soap_inlong(struct soap*, const char *tag, long *p, const char *, int); +SOAP_FMAC1 LONG64* SOAP_FMAC2 soap_inLONG64(struct soap*, const char *tag, LONG64 *p, const char *, int); +SOAP_FMAC1 short* SOAP_FMAC2 soap_inshort(struct soap*, const char *tag, short *p, const char *, int); +SOAP_FMAC1 float* SOAP_FMAC2 soap_infloat(struct soap*, const char *tag, float *p, const char *, int); +SOAP_FMAC1 double* SOAP_FMAC2 soap_indouble(struct soap*, const char *tag, double *p, const char *, int); +SOAP_FMAC1 unsigned char* SOAP_FMAC2 soap_inunsignedByte(struct soap*, const char *tag, unsigned char *p, const char *, int); +SOAP_FMAC1 unsigned short* SOAP_FMAC2 soap_inunsignedShort(struct soap*, const char *tag, unsigned short *p, const char *, int); +SOAP_FMAC1 unsigned int* SOAP_FMAC2 soap_inunsignedInt(struct soap*, const char *tag, unsigned int *p, const char *, int); +SOAP_FMAC1 unsigned long* SOAP_FMAC2 soap_inunsignedLong(struct soap*, const char *tag, unsigned long *p, const char *, int); +SOAP_FMAC1 ULONG64* SOAP_FMAC2 soap_inULONG64(struct soap*, const char *tag, ULONG64 *p, const char *, int); +SOAP_FMAC1 char** SOAP_FMAC2 soap_instring(struct soap*, const char *tag, char **p, const char *, int, int, long, long); +SOAP_FMAC1 char** SOAP_FMAC2 soap_inliteral(struct soap*, const char *tag, char **p); + +#ifndef WITH_LEAN +SOAP_FMAC1 time_t* SOAP_FMAC2 soap_indateTime(struct soap*, const char *tag, time_t *p, const char *, int); +#endif + +#ifndef WITH_LEANER +SOAP_FMAC1 wchar_t** SOAP_FMAC2 soap_inwstring(struct soap*, const char *tag, wchar_t **p, const char *, int, long, long); +SOAP_FMAC1 wchar_t** SOAP_FMAC2 soap_inwliteral(struct soap*, const char *tag, wchar_t **p); +#endif + +SOAP_FMAC1 int SOAP_FMAC2 soap_outbyte(struct soap*, const char *tag, int id, const char *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outshort(struct soap*, const char *tag, int id, const short *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outint(struct soap*, const char *tag, int id, const int *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outlong(struct soap*, const char *tag, int id, const long *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outLONG64(struct soap*, const char *tag, int id, const LONG64 *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outfloat(struct soap*, const char *tag, int id, const float *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outdouble(struct soap*, const char *tag, int id, const double *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedByte(struct soap*, const char *tag, int id, const unsigned char *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedShort(struct soap*, const char *tag, int id, const unsigned short *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedInt(struct soap*, const char *tag, int id, const unsigned int *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedLong(struct soap*, const char *tag, int id, const unsigned long *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outULONG64(struct soap*, const char *tag, int id, const ULONG64 *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outstring(struct soap*, const char *tag, int id, char *const*p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outliteral(struct soap*, const char *tag, char *const*p); + +#ifndef WITH_LEAN +SOAP_FMAC1 int SOAP_FMAC2 soap_outdateTime(struct soap*, const char *tag, int id, const time_t *p, const char *, int); +#endif + +#ifndef WITH_LEANER +SOAP_FMAC1 int SOAP_FMAC2 soap_outwstring(struct soap*, const char *tag, int id, wchar_t *const*p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outwliteral(struct soap*, const char *tag, wchar_t *const*p); +#endif + +#ifndef WITH_LEANER +SOAP_FMAC1 int SOAP_FMAC2 soap_element_dime(struct soap *, const char*, int, const void*, const struct soap_array*, const char*, const char*, const char*, int, const char*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_move(struct soap*, long); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_tell(struct soap*); +SOAP_FMAC1 char* SOAP_FMAC2 soap_dime_option(struct soap*, unsigned short, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getdimehdr(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getdime(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putdimehdr(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putdime(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getmimehdr(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getmime(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putmimehdr(struct soap*, struct soap_multipart*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putmime(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_dime(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_mime(struct soap*, const char *boundary, const char *start); +SOAP_FMAC1 void SOAP_FMAC2 soap_clr_dime(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_clr_mime(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_dime_attachment(struct soap*, char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_mime_attachment(struct soap*, char *ptr, size_t size, enum soap_mime_encoding encoding, const char *type, const char *id, const char *location, const char *description); +SOAP_FMAC1 struct soap_multipart* SOAP_FMAC2 soap_next_multipart(struct soap_multipart*); +#endif + +SOAP_FMAC1 int SOAP_FMAC2 soap_register_plugin_arg(struct soap*, int (*fcreate)(struct soap*, struct soap_plugin*, void*), void*); +SOAP_FMAC1 void* SOAP_FMAC2 soap_lookup_plugin(struct soap*, const char*); + +SOAP_FMAC1 const char* SOAP_FMAC2 soap_attr_value(struct soap *soap, const char *name, int flag); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_attr(struct soap *soap, const char *name, const char *value); +SOAP_FMAC1 void SOAP_FMAC2 soap_clr_attr(struct soap *soap); + +#ifdef WITH_COOKIES +SOAP_FMAC1 size_t SOAP_FMAC2 soap_encode_cookie(const char*, char*, size_t); +SOAP_FMAC1 extern struct soap_cookie* SOAP_FMAC2 soap_set_cookie(struct soap*, const char*, const char*, const char*, const char*); +SOAP_FMAC1 extern struct soap_cookie* SOAP_FMAC2 soap_cookie(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern char* SOAP_FMAC2 soap_cookie_value(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern long SOAP_FMAC2 soap_cookie_expire(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern int SOAP_FMAC2 soap_set_cookie_expire(struct soap*, const char*, long, const char*, const char*); +SOAP_FMAC1 extern int SOAP_FMAC2 soap_set_cookie_session(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern int SOAP_FMAC2 soap_clr_cookie_session(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern void SOAP_FMAC2 soap_clr_cookie(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern int SOAP_FMAC2 soap_getenv_cookies(struct soap*); +SOAP_FMAC1 extern struct soap_cookie* SOAP_FMAC2 soap_copy_cookies(struct soap*); +SOAP_FMAC1 extern void SOAP_FMAC2 soap_free_cookies(struct soap*); +#endif + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.10.c b/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.10.c new file mode 100644 index 0000000..ce46e28 --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.10.c @@ -0,0 +1,14890 @@ +/* + stdsoap2.c[pp] 2.7.10 + + gSOAP runtime engine + +gSOAP XML Web services tools +Copyright (C) 2000-2008, Robert van Engelen, Genivia Inc., All Rights Reserved. +This part of the software is released under ONE of the following licenses: +GPL, the gSOAP public license, OR Genivia's license for commercial use. +-------------------------------------------------------------------------------- +Contributors: + +Wind River Systems Inc., for the following additions under gSOAP public license: + - vxWorks compatible +-------------------------------------------------------------------------------- +gSOAP public license. + +The contents of this file are subject to the gSOAP Public License Version 1.3 +(the "License"); you may not use this file except in compliance with the +License. You may obtain a copy of the License at +http://www.cs.fsu.edu/~engelen/soaplicense.html +Software distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +for the specific language governing rights and limitations under the License. + +The Initial Developer of the Original Code is Robert A. van Engelen. +Copyright (C) 2000-2008, Robert van Engelen, Genivia Inc., All Rights Reserved. +-------------------------------------------------------------------------------- +GPL license. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA + +Author contact information: +engelen@genivia.com / engelen@acm.org + +This program is released under the GPL with the additional exemption that +compiling, linking, and/or using OpenSSL is allowed. +-------------------------------------------------------------------------------- +A commercial use license is available from Genivia, Inc., contact@genivia.com +-------------------------------------------------------------------------------- + +Installation note: + +Win32 build needs winsock.dll (Visual C++ "wsock32.lib") +To do this in Visual C++ 6.0, go to "Project", "settings", select the "Link" +tab (the project file needs to be selected in the file view) and add +"wsock32.lib" to the "Object/library modules" entry + +On Mac OS X with gcc (GCC) 3.1 20020420 (prerelease) you MUST compile with +-fstack_check when using -O2 because gcc 3.1 has a bug that smashes the stack +when locally allocated data exceeds 64K. + +*/ + +#ifdef AS400 +# pragma convert(819) /* EBCDIC to ASCII */ +#endif + +#include "stdsoap2.h" + +#ifdef __BORLANDC__ +# pragma warn -8060 +#else +# ifdef WIN32 +# ifdef UNDER_CE +# pragma comment(lib, "winsock.lib") +# else +# pragma comment(lib, "wsock32.lib") +# endif +# pragma warning(disable : 4996) // disable deprecation warnings +# endif +#endif + +#ifdef __cplusplus +SOAP_SOURCE_STAMP("@(#) stdsoap2.cpp ver 2.7.10 2008-01-27 00:00:00 GMT") +extern "C" { +#else +SOAP_SOURCE_STAMP("@(#) stdsoap2.c ver 2.7.10 2008-01-27 00:00:00 GMT") +#endif + +/* 8bit character representing unknown/nonrepresentable character data (e.g. not supported by current locale with multibyte support enabled) */ +#ifndef SOAP_UNKNOWN_CHAR +#define SOAP_UNKNOWN_CHAR (127) +#endif + +/* EOF=-1 */ +#define SOAP_LT (soap_wchar)(-2) /* XML character '<' */ +#define SOAP_TT (soap_wchar)(-3) /* XML character '' */ +#define SOAP_QT (soap_wchar)(-5) /* XML character '"' */ +#define SOAP_AP (soap_wchar)(-6) /* XML character ''' */ + +#define soap_blank(c) ((c) >= 0 && (c) <= 32) +#define soap_notblank(c) ((c) > 32) + +#if defined(WIN32) && !defined(UNDER_CE) +#define soap_hash_ptr(p) ((PtrToUlong(p) >> 3) & (SOAP_PTRHASH - 1)) +#else +#define soap_hash_ptr(p) ((size_t)(((unsigned long)(p) >> 3) & (SOAP_PTRHASH-1))) +#endif + +#ifdef SOAP_DEBUG +static void soap_init_logs(struct soap*); +static void soap_close_logfile(struct soap*, int); +static void soap_set_logfile(struct soap*, int, const char*); +#endif + +#ifdef SOAP_MEM_DEBUG +static void soap_init_mht(struct soap*); +static void soap_free_mht(struct soap*); +static void soap_track_unlink(struct soap*, const void*); +#endif + +#ifndef PALM_2 +static int soap_set_error(struct soap*, const char*, const char*, const char*, const char*, int); +static int soap_copy_fault(struct soap*, const char*, const char*, const char*, const char*); +static int soap_getattrval(struct soap*, char*, size_t, soap_wchar); +#endif + +#ifndef PALM_1 +static soap_wchar soap_char(struct soap*); +static soap_wchar soap_get_pi(struct soap*); +static int soap_isxdigit(int); +static void *fplugin(struct soap*, const char*); +#ifndef WITH_NOIDREF +static void soap_update_ptrs(struct soap*, char*, char*, char*, char*); +static int soap_has_copies(struct soap*, const char*, const char*); +static void soap_init_iht(struct soap*); +static void soap_free_iht(struct soap*); +static void soap_init_pht(struct soap*); +static void soap_free_pht(struct soap*); +#endif +#endif + +#ifndef WITH_LEAN +static const char *soap_set_validation_fault(struct soap*, const char*, const char*); +static int soap_isnumeric(struct soap*, const char*); +static struct soap_nlist *soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized); +static void soap_pop_ns(struct soap *soap); +static void soap_utilize_ns(struct soap *soap, const char *tag, size_t n); +#endif + +#ifndef WITH_LEANER +#ifndef PALM_1 +static struct soap_multipart *soap_new_multipart(struct soap*, struct soap_multipart**, struct soap_multipart**, char*, size_t); +static int soap_putdimefield(struct soap*, const char*, size_t); +static char *soap_getdimefield(struct soap*, size_t); +static void soap_select_mime_boundary(struct soap*); +static int soap_valid_mime_boundary(struct soap*); +static void soap_resolve_attachment(struct soap*, struct soap_multipart*); +#endif +#endif + +#ifdef WITH_GZIP +static int soap_getgziphdr(struct soap*); +#endif + +#ifdef WITH_OPENSSL +int soap_ssl_init_done = 0; + +static int ssl_auth_init(struct soap*); +static int ssl_verify_callback(int, X509_STORE_CTX*); +static int ssl_password(char*, int, int, void *); +/* The callback below is included for future references: +static DH *ssl_tmp_dh(SSL*, int, int); +*/ +#endif + +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +#ifndef PALM_1 +static const char *soap_decode(char*, size_t, const char*, const char*); +#endif +#endif + +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static soap_wchar soap_getchunkchar(struct soap*); +static const char *http_error(struct soap*, int); +static int http_post(struct soap*, const char*, const char*, int, const char*, const char*, size_t); +static int http_get(struct soap*); +static int http_put(struct soap*); +static int http_del(struct soap*); +static int http_head(struct soap*); +static int http_send_header(struct soap*, const char*); +static int http_post_header(struct soap*, const char*, const char*); +static int http_response(struct soap*, int, size_t); +static int http_parse(struct soap*); +static int http_parse_header(struct soap*, const char*, const char*); +#endif +#endif + +#ifndef WITH_NOIO + +#ifndef PALM_1 +static int fsend(struct soap*, const char*, size_t); +static size_t frecv(struct soap*, char*, size_t); +static int tcp_init(struct soap*); +static const char *tcp_error(struct soap*); +#ifndef WITH_LEAN +static size_t frecv_stop(struct soap*, char*, size_t); +#endif +#ifndef WITH_IPV6 +static int tcp_gethost(struct soap*, const char *addr, struct in_addr *inaddr); +#endif +static SOAP_SOCKET tcp_connect(struct soap*, const char *endpoint, const char *host, int port); +static SOAP_SOCKET tcp_accept(struct soap*, SOAP_SOCKET, struct sockaddr*, int*); +static int tcp_disconnect(struct soap*); +static int tcp_closesocket(struct soap*, SOAP_SOCKET); +static int tcp_shutdownsocket(struct soap*, SOAP_SOCKET, int); +static const char *soap_strerror(struct soap*); +#endif + +#if defined(WIN32) + #define SOAP_SOCKBLOCK(fd) \ + { u_long blocking = 0; \ + ioctlsocket(fd, FIONBIO, &blocking); \ + } + #define SOAP_SOCKNONBLOCK(fd) \ + { u_long nonblocking = 1; \ + ioctlsocket(fd, FIONBIO, &nonblocking); \ + } +#elif defined(VXWORKS) + #define SOAP_SOCKBLOCK(fd) \ + { u_long blocking = 0; \ + ioctl(fd, FIONBIO, (int)(&blocking)); \ + } + #define SOAP_SOCKNONBLOCK(fd) \ + { u_long nonblocking = 1; \ + ioctl(fd, FIONBIO, (int)(&nonblocking)); \ + } +#elif defined(PALM) + #define SOAP_SOCKBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)&~O_NONBLOCK); + #define SOAP_SOCKNONBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0)|O_NONBLOCK); +#elif defined(SYMBIAN) + #define SOAP_SOCKBLOCK(fd) \ + { long blocking = 0; \ + ioctl(fd, 0/*FIONBIO*/, &blocking); \ + } + #define SOAP_SOCKNONBLOCK(fd) \ + { long nonblocking = 1; \ + ioctl(fd, 0/*FIONBIO*/, &nonblocking); \ + } +#else + #define SOAP_SOCKBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)&~O_NONBLOCK); + #define SOAP_SOCKNONBLOCK(fd) fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)|O_NONBLOCK); +#endif + +#endif + +#if defined(PALM) && !defined(PALM_2) +unsigned short errno; +#endif + +#ifndef PALM_1 +static const char soap_env1[42] = "http://schemas.xmlsoap.org/soap/envelope/"; +static const char soap_enc1[42] = "http://schemas.xmlsoap.org/soap/encoding/"; +static const char soap_env2[40] = "http://www.w3.org/2003/05/soap-envelope"; +static const char soap_enc2[40] = "http://www.w3.org/2003/05/soap-encoding"; +static const char soap_rpc[35] = "http://www.w3.org/2003/05/soap-rpc"; +#endif + +#ifndef PALM_1 +const struct soap_double_nan soap_double_nan = {0xFFFFFFFF, 0xFFFFFFFF}; +static const char soap_base64o[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char soap_base64i[81] = "\76XXX\77\64\65\66\67\70\71\72\73\74\75XXXXXXX\00\01\02\03\04\05\06\07\10\11\12\13\14\15\16\17\20\21\22\23\24\25\26\27\30\31XXXXXX\32\33\34\35\36\37\40\41\42\43\44\45\46\47\50\51\52\53\54\55\56\57\60\61\62\63"; +#endif + +#ifndef WITH_LEAN +static const char soap_indent[11] = "\n\t\t\t\t\t\t\t\t\t"; +/* Alternative indentation form for SOAP_XML_INDENT: +static const char soap_indent[21] = "\n "; +*/ +#endif + +#ifndef SOAP_CANARY +# define SOAP_CANARY (0xC0DE) +#endif + +static const char soap_padding[4] = "\0\0\0"; +#define SOAP_STR_PADDING (soap_padding) +#define SOAP_STR_EOS (soap_padding) +#define SOAP_NON_NULL (soap_padding) + +#ifndef WITH_LEAN +static const struct soap_code_map html_entity_codes[] = /* entities for XHTML parsing */ +{ { 160, "nbsp" }, + { 161, "iexcl" }, + { 162, "cent" }, + { 163, "pound" }, + { 164, "curren" }, + { 165, "yen" }, + { 166, "brvbar" }, + { 167, "sect" }, + { 168, "uml" }, + { 169, "copy" }, + { 170, "ordf" }, + { 171, "laquo" }, + { 172, "not" }, + { 173, "shy" }, + { 174, "reg" }, + { 175, "macr" }, + { 176, "deg" }, + { 177, "plusmn" }, + { 178, "sup2" }, + { 179, "sup3" }, + { 180, "acute" }, + { 181, "micro" }, + { 182, "para" }, + { 183, "middot" }, + { 184, "cedil" }, + { 185, "sup1" }, + { 186, "ordm" }, + { 187, "raquo" }, + { 188, "frac14" }, + { 189, "frac12" }, + { 190, "frac34" }, + { 191, "iquest" }, + { 192, "Agrave" }, + { 193, "Aacute" }, + { 194, "Acirc" }, + { 195, "Atilde" }, + { 196, "Auml" }, + { 197, "Aring" }, + { 198, "AElig" }, + { 199, "Ccedil" }, + { 200, "Egrave" }, + { 201, "Eacute" }, + { 202, "Ecirc" }, + { 203, "Euml" }, + { 204, "Igrave" }, + { 205, "Iacute" }, + { 206, "Icirc" }, + { 207, "Iuml" }, + { 208, "ETH" }, + { 209, "Ntilde" }, + { 210, "Ograve" }, + { 211, "Oacute" }, + { 212, "Ocirc" }, + { 213, "Otilde" }, + { 214, "Ouml" }, + { 215, "times" }, + { 216, "Oslash" }, + { 217, "Ugrave" }, + { 218, "Uacute" }, + { 219, "Ucirc" }, + { 220, "Uuml" }, + { 221, "Yacute" }, + { 222, "THORN" }, + { 223, "szlig" }, + { 224, "agrave" }, + { 225, "aacute" }, + { 226, "acirc" }, + { 227, "atilde" }, + { 228, "auml" }, + { 229, "aring" }, + { 230, "aelig" }, + { 231, "ccedil" }, + { 232, "egrave" }, + { 233, "eacute" }, + { 234, "ecirc" }, + { 235, "euml" }, + { 236, "igrave" }, + { 237, "iacute" }, + { 238, "icirc" }, + { 239, "iuml" }, + { 240, "eth" }, + { 241, "ntilde" }, + { 242, "ograve" }, + { 243, "oacute" }, + { 244, "ocirc" }, + { 245, "otilde" }, + { 246, "ouml" }, + { 247, "divide" }, + { 248, "oslash" }, + { 249, "ugrave" }, + { 250, "uacute" }, + { 251, "ucirc" }, + { 252, "uuml" }, + { 253, "yacute" }, + { 254, "thorn" }, + { 255, "yuml" }, + { 0, NULL } +}; +#endif + +#ifndef WITH_NOIO +#ifndef WITH_LEAN +static const struct soap_code_map h_error_codes[] = +{ +#ifdef HOST_NOT_FOUND + { HOST_NOT_FOUND, "Host not found" }, +#endif +#ifdef TRY_AGAIN + { TRY_AGAIN, "Try Again" }, +#endif +#ifdef NO_RECOVERY + { NO_RECOVERY, "No Recovery" }, +#endif +#ifdef NO_DATA + { NO_DATA, "No Data" }, +#endif +#ifdef NO_ADDRESS + { NO_ADDRESS, "No Address" }, +#endif + { 0, NULL } +}; +#endif +#endif + +#ifndef WITH_NOHTTP +#ifndef WITH_LEAN +static const struct soap_code_map h_http_error_codes[] = +{ { 200, "OK" }, + { 201, "Created" }, + { 202, "Accepted" }, + { 203, "Non-Authoritative Information" }, + { 204, "No Content" }, + { 205, "Reset Content" }, + { 206, "Partial Content" }, + { 300, "Multiple Choices" }, + { 301, "Moved Permanently" }, + { 302, "Found" }, + { 303, "See Other" }, + { 304, "Not Modified" }, + { 305, "Use Proxy" }, + { 307, "Temporary Redirect" }, + { 400, "Bad Request" }, + { 401, "Unauthorized" }, + { 402, "Payment Required" }, + { 403, "Forbidden" }, + { 404, "Not Found" }, + { 405, "Method Not Allowed" }, + { 406, "Not Acceptable" }, + { 407, "Proxy Authentication Required" }, + { 408, "Request Time-out" }, + { 409, "Conflict" }, + { 410, "Gone" }, + { 411, "Length Required" }, + { 412, "Precondition Failed" }, + { 413, "Request Entity Too Large" }, + { 414, "Request-URI Too Large" }, + { 415, "Unsupported Media Type" }, + { 416, "Requested range not satisfiable" }, + { 417, "Expectation Failed" }, + { 500, "Internal Server Error" }, + { 501, "Not Implemented" }, + { 502, "Bad Gateway" }, + { 503, "Service Unavailable" }, + { 504, "Gateway Time-out" }, + { 505, "HTTP Version not supported" }, + { 0, NULL } +}; +#endif +#endif + +#ifdef WITH_OPENSSL +static const struct soap_code_map h_ssl_error_codes[] = +{ +#define _SSL_ERROR(e) { e, #e } + _SSL_ERROR(SSL_ERROR_SSL), + _SSL_ERROR(SSL_ERROR_ZERO_RETURN), + _SSL_ERROR(SSL_ERROR_WANT_READ), + _SSL_ERROR(SSL_ERROR_WANT_WRITE), + _SSL_ERROR(SSL_ERROR_WANT_CONNECT), + _SSL_ERROR(SSL_ERROR_WANT_X509_LOOKUP), + _SSL_ERROR(SSL_ERROR_SYSCALL), + { 0, NULL } +}; +#endif + +#ifndef WITH_LEANER +static const struct soap_code_map mime_codes[] = +{ { SOAP_MIME_7BIT, "7bit" }, + { SOAP_MIME_8BIT, "8bit" }, + { SOAP_MIME_BINARY, "binary" }, + { SOAP_MIME_QUOTED_PRINTABLE, "quoted-printable" }, + { SOAP_MIME_BASE64, "base64" }, + { SOAP_MIME_IETF_TOKEN, "ietf-token" }, + { SOAP_MIME_X_TOKEN, "x-token" }, + { 0, NULL } +}; +#endif + +#ifdef WIN32 +static int tcp_done = 0; +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +fsend(struct soap *soap, const char *s, size_t n) +{ register int nwritten, err; +#if defined(__cplusplus) && !defined(WITH_LEAN) + if (soap->os) + { soap->os->write(s, (std::streamsize)n); + if (soap->os->good()) + return SOAP_OK; + soap->errnum = 0; + return SOAP_EOF; + } +#endif + while (n) + { if (soap_valid_socket(soap->socket)) + { +#ifndef WITH_LEAN + if (soap->send_timeout) + { +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + return SOAP_FD_EXCEEDED; /* Hint: MUST increase FD_SETSIZE */ +#endif + for (;;) + { struct timeval timeout; + fd_set fd; + register int r; + if (soap->send_timeout > 0) + { timeout.tv_sec = soap->send_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->send_timeout/1000000; + timeout.tv_usec = -soap->send_timeout%1000000; + } + FD_ZERO(&fd); + FD_SET(soap->socket, &fd); +#ifdef WITH_OPENSSL + if (soap->ssl) + r = select((int)soap->socket + 1, &fd, &fd, &fd, &timeout); + else +#endif + r = select((int)soap->socket + 1, NULL, &fd, &fd, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + return SOAP_EOF; + } + err = soap_socket_errno(soap->socket); + if (err != SOAP_EINTR && err != SOAP_EAGAIN && err != SOAP_EWOULDBLOCK) + { soap->errnum = err; + return SOAP_EOF; + } + } + } +#endif +#ifdef WITH_OPENSSL + if (soap->ssl) + nwritten = SSL_write(soap->ssl, s, (int)n); + else if (soap->bio) + nwritten = BIO_write(soap->bio, s, (int)n); + else +#endif +#ifndef WITH_LEAN + if ((soap->omode & SOAP_IO_UDP)) + { if (soap->peerlen) + nwritten = sendto(soap->socket, s, (SOAP_WINSOCKINT)n, soap->socket_flags, (struct sockaddr*)&soap->peer, (SOAP_WINSOCKINT)soap->peerlen); + else + nwritten = send(soap->socket, s, (SOAP_WINSOCKINT)n, soap->socket_flags); + /* retry and back-off algorithm */ + /* TODO: this is not very clear from specs so verify and limit conditions under which we should loop (e.g. ENOBUFS) */ + if (nwritten < 0) + { struct timeval timeout; + fd_set fd; + int udp_repeat; + int udp_delay; +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + return SOAP_FD_EXCEEDED; /* Hint: MUST increase FD_SETSIZE */ +#endif + if ((soap->connect_flags & SO_BROADCAST)) + udp_repeat = 3; /* SOAP-over-UDP MULTICAST_UDP_REPEAT - 1 */ + else + udp_repeat = 1; /* SOAP-over-UDP UNICAST_UDP_REPEAT - 1 */ + udp_delay = (soap_random % 201) + 50; /* UDP_MIN_DELAY .. UDP_MAX_DELAY */ + do + { timeout.tv_sec = 0; + timeout.tv_usec = 1000 * udp_delay; /* ms */ + FD_ZERO(&fd); + FD_SET(soap->socket, &fd); + select((int)soap->socket + 1, NULL, NULL, &fd, &timeout); + if (soap->peerlen) + nwritten = sendto(soap->socket, s, (SOAP_WINSOCKINT)n, soap->socket_flags, (struct sockaddr*)&soap->peer, (SOAP_WINSOCKINT)soap->peerlen); + else + nwritten = send(soap->socket, s, (SOAP_WINSOCKINT)n, soap->socket_flags); + udp_delay <<= 1; + if (udp_delay > 500) /* UDP_UPPER_DELAY */ + udp_delay = 500; + } + while (nwritten < 0 && --udp_repeat > 0); + } + } + else +#endif +#if !defined(PALM) && !defined(AS400) + nwritten = send(soap->socket, s, (int)n, soap->socket_flags); +#else + nwritten = send(soap->socket, (void*)s, n, soap->socket_flags); +#endif + if (nwritten <= 0) + { +#if defined(WITH_OPENSSL) || !defined(WITH_LEAN) + register int r = 0; +#endif + err = soap_socket_errno(soap->socket); +#ifdef WITH_OPENSSL + if (soap->ssl && (r = SSL_get_error(soap->ssl, nwritten)) != SSL_ERROR_NONE && r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE) + { soap->errnum = err; + return SOAP_EOF; + } +#endif + if (err == SOAP_EWOULDBLOCK || err == SOAP_EAGAIN) + { +#ifndef WITH_LEAN + struct timeval timeout; + fd_set fd; +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + return SOAP_FD_EXCEEDED; /* Hint: MUST increase FD_SETSIZE */ +#endif + if (soap->send_timeout > 0) + { timeout.tv_sec = soap->send_timeout; + timeout.tv_usec = 0; + } + else if (soap->send_timeout < 0) + { timeout.tv_sec = -soap->send_timeout/1000000; + timeout.tv_usec = -soap->send_timeout%1000000; + } + else + { timeout.tv_sec = 0; + timeout.tv_usec = 10000; + } + FD_ZERO(&fd); + FD_SET(soap->socket, &fd); +#ifdef WITH_OPENSSL + if (soap->ssl && r == SSL_ERROR_WANT_READ) + r = select((int)soap->socket + 1, &fd, NULL, &fd, &timeout); + else + r = select((int)soap->socket + 1, NULL, &fd, &fd, &timeout); +#else + r = select((int)soap->socket + 1, NULL, &fd, &fd, &timeout); +#endif + if (r < 0 && (r = soap_socket_errno(soap->socket)) != SOAP_EINTR) + { soap->errnum = r; + return SOAP_EOF; + } +#endif + } + else if (err && err != SOAP_EINTR) + { soap->errnum = err; + return SOAP_EOF; + } + nwritten = 0; /* and call write() again */ + } + } + else + { +#ifdef WITH_FASTCGI + nwritten = fwrite((void*)s, 1, n, stdout); + fflush(stdout); +#else +#ifdef UNDER_CE + nwritten = fwrite(s, 1, n, soap->sendfd); +#else +#ifdef VXWORKS +#ifdef WMW_RPM_IO + if (soap->rpmreqid) + nwritten = (httpBlockPut(soap->rpmreqid, s, n) == 0) ? n : -1; + else +#endif + nwritten = fwrite(s, sizeof(char), n, fdopen(soap->sendfd, "w")); +#else + nwritten = write(soap->sendfd, s, (unsigned int)n); +#endif +#endif +#endif + if (nwritten <= 0) + { err = soap_errno; + if (err && err != SOAP_EINTR && err != SOAP_EWOULDBLOCK && err != SOAP_EAGAIN) + { soap->errnum = err; + return SOAP_EOF; + } + nwritten = 0; /* and call write() again */ + } + } + n -= nwritten; + s += nwritten; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send_raw(struct soap *soap, const char *s, size_t n) +{ if (!n) + return SOAP_OK; + if (soap->mode & SOAP_IO_LENGTH) + { soap->count += n; +#ifndef WITH_LEANER + if (soap->fpreparesend && (soap->mode & SOAP_IO) != SOAP_IO_STORE) + return soap->error = soap->fpreparesend(soap, s, n); +#endif + return SOAP_OK; + } + if (soap->mode & SOAP_IO) + { register size_t i = SOAP_BUFLEN - soap->bufidx; + while (n >= i) + { memcpy(soap->buf + soap->bufidx, s, i); + soap->bufidx = SOAP_BUFLEN; + if (soap_flush(soap)) + return soap->error; + s += i; + n -= i; + i = SOAP_BUFLEN; + } + memcpy(soap->buf + soap->bufidx, s, n); + soap->bufidx += n; + return SOAP_OK; + } + return soap_flush_raw(soap, s, n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_flush(struct soap *soap) +{ register size_t n = soap->bufidx; + if (n) + { soap->bufidx = 0; +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { soap->d_stream->next_in = (Byte*)soap->buf; + soap->d_stream->avail_in = (unsigned int)n; +#ifdef WITH_GZIP + soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)n); +#endif + do + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating %u bytes\n", soap->d_stream->avail_in)); + if (deflate(soap->d_stream, Z_NO_FLUSH) != Z_OK) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to deflate: %s\n", soap->d_stream->msg?soap->d_stream->msg:"")); + return soap->error = SOAP_ZLIB_ERROR; + } + if (!soap->d_stream->avail_out) + { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN)) + return soap->error; + soap->d_stream->next_out = (Byte*)soap->z_buf; + soap->d_stream->avail_out = SOAP_BUFLEN; + } + } while (soap->d_stream->avail_in); + } + else +#endif + return soap_flush_raw(soap, soap->buf, n); + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_flush_raw(struct soap *soap, const char *s, size_t n) +{ if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) + { register char *t; + if (!(t = (char*)soap_push_block(soap, n))) + return soap->error = SOAP_EOM; + memcpy(t, s, n); +#ifndef WITH_LEANER + if (soap->fpreparesend) + return soap->error = soap->fpreparesend(soap, s, n); +#endif + return SOAP_OK; + } +#ifndef WITH_LEANER + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) + { char t[16]; + sprintf(t, "\r\n%lX\r\n" + (soap->chunksize ? 0 : 2), (unsigned long)n); + DBGMSG(SENT, t, strlen(t)); + if ((soap->error = soap->fsend(soap, t, strlen(t)))) + return soap->error; + soap->chunksize += n; + } + DBGMSG(SENT, s, n); +#endif + return soap->error = soap->fsend(soap, s, n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send(struct soap *soap, const char *s) +{ if (s) + return soap_send_raw(soap, s, strlen(s)); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send2(struct soap *soap, const char *s1, const char *s2) +{ if (soap_send(soap, s1)) + return soap->error; + return soap_send(soap, s2); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send3(struct soap *soap, const char *s1, const char *s2, const char *s3) +{ if (soap_send(soap, s1) + || soap_send(soap, s2)) + return soap->error; + return soap_send(soap, s3); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static size_t +frecv(struct soap *soap, char *s, size_t n) +{ register int r; +#ifndef WITH_LEAN + register int retries = 100; /* max 100 retries with non-blocking sockets */ +#endif + soap->errnum = 0; +#if defined(__cplusplus) && !defined(WITH_LEAN) + if (soap->is) + { if (soap->is->good()) + return soap->is->read(s, (std::streamsize)n).gcount(); + return 0; + } +#endif + if (soap_valid_socket(soap->socket)) + { for (;;) + { +#ifdef WITH_OPENSSL + register int err = 0; +#endif +#ifndef WITH_LEAN +#ifdef WITH_OPENSSL + if (soap->recv_timeout && !soap->ssl) /* SSL: sockets are nonblocking */ +#else + if (soap->recv_timeout) +#endif + { +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + { soap->error = SOAP_FD_EXCEEDED; + return 0; /* Hint: MUST increase FD_SETSIZE */ + } +#endif + for (;;) + { struct timeval timeout; + fd_set fd; + if (soap->recv_timeout > 0) + { timeout.tv_sec = soap->recv_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->recv_timeout/1000000; + timeout.tv_usec = -soap->recv_timeout%1000000; + } + FD_ZERO(&fd); + FD_SET(soap->socket, &fd); + r = select((int)soap->socket + 1, &fd, NULL, &fd, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + return 0; + } + r = soap_socket_errno(soap->socket); + if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK) + { soap->errnum = r; + return 0; + } + } + } +#endif +#ifdef WITH_OPENSSL + if (soap->ssl) + { r = SSL_read(soap->ssl, s, (int)n); + if (r > 0) + return (size_t)r; + err = SSL_get_error(soap->ssl, r); + if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) + return 0; + } + else if (soap->bio) + { r = BIO_read(soap->bio, s, (int)n); + if (r > 0) + return (size_t)r; + return 0; + } + else +#endif + { +#ifndef WITH_LEAN + if ((soap->omode & SOAP_IO_UDP)) + { SOAP_SOCKLEN_T k = (SOAP_SOCKLEN_T)sizeof(soap->peer); + memset((void*)&soap->peer, 0, sizeof(soap->peer)); + r = recvfrom(soap->socket, s, (SOAP_WINSOCKINT)n, soap->socket_flags, (struct sockaddr*)&soap->peer, &k); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */ + soap->peerlen = (size_t)k; +#ifndef WITH_IPV6 + soap->ip = ntohl(soap->peer.sin_addr.s_addr); +#endif + } + else +#endif + r = recv(soap->socket, s, (int)n, soap->socket_flags); +#ifdef PALM + /* CycleSyncDisplay(curStatusMsg); */ +#endif + if (r >= 0) + return (size_t)r; + r = soap_socket_errno(soap->socket); + if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK) + { soap->errnum = r; + return 0; + } + } +#ifndef WITH_LEAN + { struct timeval timeout; + fd_set fd; + if (soap->recv_timeout > 0) + { timeout.tv_sec = soap->recv_timeout; + timeout.tv_usec = 0; + } + else if (soap->recv_timeout < 0) + { timeout.tv_sec = -soap->recv_timeout/1000000; + timeout.tv_usec = -soap->recv_timeout%1000000; + } + else + { timeout.tv_sec = 5; + timeout.tv_usec = 0; + } +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + { soap->error = SOAP_FD_EXCEEDED; + return 0; /* Hint: MUST increase FD_SETSIZE */ + } +#endif + FD_ZERO(&fd); + FD_SET(soap->socket, &fd); +#ifdef WITH_OPENSSL + if (soap->ssl && err == SSL_ERROR_WANT_WRITE) + r = select((int)soap->socket + 1, NULL, &fd, &fd, &timeout); + else + r = select((int)soap->socket + 1, &fd, NULL, &fd, &timeout); +#else + r = select((int)soap->socket + 1, &fd, NULL, &fd, &timeout); +#endif + if (!r && soap->recv_timeout) + { soap->errnum = 0; + return 0; + } + if (r < 0) + { r = soap_socket_errno(soap->socket); + if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK) + { soap->errnum = r; + return 0; + } + } + if (retries-- <= 0) + { soap->errnum = soap_socket_errno(soap->socket); + return 0; + } + } +#endif +#ifdef PALM + r = soap_socket_errno(soap->socket); + if (r != SOAP_EINTR && retries-- <= 0) + { soap->errnum = r; + return 0; + } +#endif + } + } +#ifdef WITH_FASTCGI + return fread(s, 1, n, stdin); +#else +#ifdef UNDER_CE + return fread(s, 1, n, soap->recvfd); +#else +#ifdef WMW_RPM_IO + if (soap->rpmreqid) + r = httpBlockRead(soap->rpmreqid, s, n); + else +#endif + r = read(soap->recvfd, s, (unsigned int)n); + if (r >= 0) + return (size_t)r; + soap->errnum = soap_errno; + return 0; +#endif +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +#ifndef WITH_NOIO +#ifndef PALM_1 +static size_t +frecv_stop(struct soap *soap, char *s, size_t n) +{ return 0; +} +#endif +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static soap_wchar +soap_getchunkchar(struct soap *soap) +{ if (soap->bufidx < soap->buflen) + return soap->buf[soap->bufidx++]; + soap->bufidx = 0; + soap->buflen = soap->chunkbuflen = soap->frecv(soap, soap->buf, SOAP_BUFLEN); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket %d\n", (unsigned int)soap->buflen, soap->socket)); + DBGMSG(RECV, soap->buf, soap->buflen); + if (soap->buflen) + return soap->buf[soap->bufidx++]; + return EOF; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +soap_isxdigit(int c) +{ return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv_raw(struct soap *soap) +{ register size_t ret; +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { if (soap->d_stream->next_out == Z_NULL) + return EOF; + if (soap->d_stream->avail_in || !soap->d_stream->avail_out) + { register int r; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflating\n")); + soap->d_stream->next_out = (Byte*)soap->buf; + soap->d_stream->avail_out = SOAP_BUFLEN; + r = inflate(soap->d_stream, Z_NO_FLUSH); + if (r == Z_OK || r == Z_STREAM_END) + { soap->bufidx = 0; + ret = soap->buflen = SOAP_BUFLEN - soap->d_stream->avail_out; + if (soap->zlib_in == SOAP_ZLIB_GZIP) + soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)ret); + if (r == Z_STREAM_END) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out)); + soap->z_ratio_in = (float)soap->d_stream->total_in / (float)soap->d_stream->total_out; + soap->d_stream->next_out = Z_NULL; + } + if (ret) + { soap->count += ret; + DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- decompressed ----\n")); + DBGMSG(RECV, soap->buf, ret); + DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n----\n")); + return SOAP_OK; + } + } + else if (r != Z_BUF_ERROR) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate error: %s\n", soap->d_stream->msg?soap->d_stream->msg:"")); + soap->d_stream->next_out = Z_NULL; + soap->error = SOAP_ZLIB_ERROR; + return EOF; + } + } +zlib_again: + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK && !soap->chunksize) + { memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN); + soap->buflen = soap->z_buflen; + } + DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- compressed ----\n")); + } +#endif +#ifndef WITH_NOHTTP + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) /* read HTTP chunked transfer */ + { for (;;) + { register soap_wchar c; + char *t, tmp[8]; + if (soap->chunksize) + { soap->buflen = ret = soap->frecv(soap, soap->buf, soap->chunksize > SOAP_BUFLEN ? SOAP_BUFLEN : soap->chunksize); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk: read %u bytes\n", (unsigned int)ret)); + DBGMSG(RECV, soap->buf, ret); + soap->bufidx = 0; + soap->chunksize -= ret; + break; + } + t = tmp; + if (!soap->chunkbuflen) + { soap->chunkbuflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes (chunked) from socket %d\n", (unsigned int)ret, soap->socket)); + DBGMSG(RECV, soap->buf, ret); + soap->bufidx = 0; + if (!ret) + return soap->ahead = EOF; + } + else + soap->bufidx = soap->buflen; + soap->buflen = soap->chunkbuflen; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk size (idx=%u len=%u)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen)); + while (!soap_isxdigit((int)(c = soap_getchunkchar(soap)))) + { if ((int)c == EOF) + return soap->ahead = EOF; + } + do + *t++ = (char)c; + while (soap_isxdigit((int)(c = soap_getchunkchar(soap))) && t - tmp < 7); + while ((int)c != EOF && c != '\n') + c = soap_getchunkchar(soap); + if ((int)c == EOF) + return soap->ahead = EOF; + *t = '\0'; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunk size = %s (hex)\n", tmp)); + soap->chunksize = soap_strtoul(tmp, &t, 16); + if (!soap->chunksize) + { soap->chunkbuflen = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of chunked message\n")); + while ((int)c != EOF && c != '\n') + c = soap_getchunkchar(soap); + ret = 0; + soap->ahead = EOF; + break; + } + soap->buflen = soap->bufidx + soap->chunksize; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving buf len to idx=%u len=%u (%s)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen, tmp)); + if (soap->buflen > soap->chunkbuflen) + { soap->buflen = soap->chunkbuflen; + soap->chunksize -= soap->buflen - soap->bufidx; + soap->chunkbuflen = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Passed end of buffer for chunked HTTP (%u bytes left)\n", (unsigned int)(soap->buflen - soap->bufidx))); + } + else if (soap->chunkbuflen) + soap->chunksize = 0; + ret = soap->buflen - soap->bufidx; + if (ret) + break; + } + } + else +#endif + { soap->bufidx = 0; + soap->buflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket %d\n", (unsigned int)ret, soap->socket)); + DBGMSG(RECV, soap->buf, ret); + } +#ifndef WITH_LEANER + if (soap->fpreparerecv && (soap->error = soap->fpreparerecv(soap, soap->buf, ret))) + return soap->error; +#endif +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { register int r; + memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); + soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx); + soap->d_stream->avail_in = (unsigned int)ret; + soap->d_stream->next_out = (Byte*)soap->buf; + soap->d_stream->avail_out = SOAP_BUFLEN; + r = inflate(soap->d_stream, Z_NO_FLUSH); + if (r == Z_OK || r == Z_STREAM_END) + { soap->bufidx = 0; + soap->z_buflen = soap->buflen; + soap->buflen = SOAP_BUFLEN - soap->d_stream->avail_out; + if (soap->zlib_in == SOAP_ZLIB_GZIP) + soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %u bytes\n", (unsigned int)soap->buflen)); + if (ret && !soap->buflen) + goto zlib_again; + ret = soap->buflen; + if (r == Z_STREAM_END) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated total %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out)); + soap->z_ratio_in = (float)soap->d_stream->total_in / (float)soap->d_stream->total_out; + soap->d_stream->next_out = Z_NULL; + } + DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- decompressed ----\n")); + DBGMSG(RECV, soap->buf, ret); + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to inflate: (%d) %s\n", r, soap->d_stream->msg?soap->d_stream->msg:"")); + soap->d_stream->next_out = Z_NULL; + soap->error = SOAP_ZLIB_ERROR; + return EOF; + } + } +#endif + soap->count += ret; + return !ret; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv(struct soap *soap) +{ +#ifndef WITH_LEANER + if (soap->mode & SOAP_ENC_DIME) + { if (soap->dime.buflen) + { char *s; + int i; + unsigned char tmp[12]; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME hdr for chunked DIME is in buffer\n")); + soap->count += soap->dime.buflen - soap->buflen; + soap->buflen = soap->dime.buflen; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Skip padding (%ld bytes)\n", -(long)soap->dime.size&3)); + for (i = -(long)soap->dime.size&3; i > 0; i--) + { soap->bufidx++; + if (soap->bufidx >= soap->buflen) + if (soap_recv_raw(soap)) + return EOF; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME hdr for next chunk\n")); + s = (char*)tmp; + for (i = 12; i > 0; i--) + { *s++ = soap->buf[soap->bufidx++]; + if (soap->bufidx >= soap->buflen) + if (soap_recv_raw(soap)) + return EOF; + } + soap->dime.flags = tmp[0] & 0x7; + soap->dime.size = ((size_t)tmp[8] << 24) | ((size_t)tmp[9] << 16) | ((size_t)tmp[10] << 8) | ((size_t)tmp[11]); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME chunk (%u bytes)\n", (unsigned int)soap->dime.size)); + if (soap->dime.flags & SOAP_DIME_CF) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "More chunking\n")); + soap->dime.chunksize = soap->dime.size; + if (soap->buflen - soap->bufidx >= soap->dime.size) + { soap->dime.buflen = soap->buflen; + soap->buflen = soap->bufidx + soap->dime.chunksize; + } + else + soap->dime.chunksize -= soap->buflen - soap->bufidx; + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Last chunk\n")); + soap->dime.buflen = 0; + soap->dime.chunksize = 0; + } + soap->count = soap->buflen - soap->bufidx; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%u bytes remaining\n", (unsigned int)soap->count)); + return SOAP_OK; + } + if (soap->dime.chunksize) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get next DIME hdr for chunked DIME (%u bytes chunk)\n", (unsigned int)soap->dime.chunksize)); + if (soap_recv_raw(soap)) + return EOF; + if (soap->buflen - soap->bufidx >= soap->dime.chunksize) + { soap->dime.buflen = soap->buflen; + soap->count -= soap->buflen - soap->bufidx - soap->dime.chunksize; + soap->buflen = soap->bufidx + soap->dime.chunksize; + } + else + soap->dime.chunksize -= soap->buflen - soap->bufidx; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%lu bytes remaining, count=%u\n", (unsigned long)(soap->buflen-soap->bufidx), (unsigned int)soap->count)); + return SOAP_OK; + } + } +#endif + return soap_recv_raw(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +soap_wchar +SOAP_FMAC2 +soap_getchar(struct soap *soap) +{ register soap_wchar c; + c = soap->ahead; + if (c) + { if (c != EOF) + soap->ahead = 0; + return c; + } + return soap_get1(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +const struct soap_code_map* +SOAP_FMAC2 +soap_code(const struct soap_code_map *code_map, const char *str) +{ if (code_map && str) + { while (code_map->string) + { if (!strcmp(str, code_map->string)) /* case sensitive */ + return code_map; + code_map++; + } + } + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +long +SOAP_FMAC2 +soap_code_int(const struct soap_code_map *code_map, const char *str, long other) +{ if (code_map) + { while (code_map->string) + { if (!soap_tag_cmp(str, code_map->string)) /* case insensitive */ + return code_map->code; + code_map++; + } + } + return other; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_code_str(const struct soap_code_map *code_map, long code) +{ if (!code_map) + return NULL; + while (code_map->code != code && code_map->string) + code_map++; + return code_map->string; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +long +SOAP_FMAC2 +soap_code_bits(const struct soap_code_map *code_map, const char *str) +{ register long bits = 0; + if (code_map) + { while (str && *str) + { const struct soap_code_map *p; + for (p = code_map; p->string; p++) + { register size_t n = strlen(p->string); + if (!strncmp(p->string, str, n) && soap_blank(str[n])) + { bits |= p->code; + str += n; + while (*str > 0 && *str <= 32) + str++; + break; + } + } + if (!p->string) + return 0; + } + } + return bits; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_code_list(struct soap *soap, const struct soap_code_map *code_map, long code) +{ register char *t = soap->tmpbuf; + if (code_map) + { while (code_map->string) + { if (code_map->code & code) + { register const char *s = code_map->string; + if (t != soap->tmpbuf) + *t++ = ' '; + while (*s && t < soap->tmpbuf + sizeof(soap->tmpbuf) - 1) + *t++ = *s++; + if (t == soap->tmpbuf + sizeof(soap->tmpbuf) - 1) + break; + } + code_map++; + } + } + *t = '\0'; + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static soap_wchar +soap_char(struct soap *soap) +{ char tmp[8]; + register int i; + register soap_wchar c; + register char *s = tmp; + for (i = 0; i < 7; i++) + { c = soap_get1(soap); + if (c == ';' || (int)c == EOF) + break; + *s++ = (char)c; + } + *s = '\0'; + if (*tmp == '#') + { if (tmp[1] == 'x' || tmp[1] == 'X') + return soap_strtol(tmp + 2, NULL, 16); + return atol(tmp + 1); + } + if (!strcmp(tmp, "lt")) + return '<'; + if (!strcmp(tmp, "gt")) + return '>'; + if (!strcmp(tmp, "amp")) + return '&'; + if (!strcmp(tmp, "quot")) + return '"'; + if (!strcmp(tmp, "apos")) + return '\''; +#ifndef WITH_LEAN + return (soap_wchar)soap_code_int(html_entity_codes, tmp, SOAP_UNKNOWN_CHAR); +#else + return SOAP_UNKNOWN_CHAR; /* use this to represent unknown code */ +#endif +} +#endif + +/******************************************************************************/ +#ifdef WITH_LEAN +#ifndef PALM_1 +soap_wchar +soap_get0(struct soap *soap) +{ if (soap->bufidx >= soap->buflen && soap_recv(soap)) + return EOF; + return (unsigned char)soap->buf[soap->bufidx]; +} +#endif +#endif + +/******************************************************************************/ +#ifdef WITH_LEAN +#ifndef PALM_1 +soap_wchar +soap_get1(struct soap *soap) +{ if (soap->bufidx >= soap->buflen && soap_recv(soap)) + return EOF; + return (unsigned char)soap->buf[soap->bufidx++]; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +soap_wchar +SOAP_FMAC2 +soap_get(struct soap *soap) +{ register soap_wchar c; + c = soap->ahead; + if (c) + { if ((int)c != EOF) + soap->ahead = 0; + } + else + c = soap_get1(soap); + while ((int)c != EOF) + { if (soap->cdata) + { if (c == ']') + { c = soap_get1(soap); + if (c == ']') + { c = soap_get0(soap); + if (c == '>') + { soap->cdata = 0; + soap_get1(soap); + c = soap_get1(soap); + } + else + { soap_unget(soap, ']'); + return ']'; + } + } + else + { soap_revget1(soap); + return ']'; + } + } + else + return c; + } + switch (c) + { case '<': + do c = soap_get1(soap); + while (soap_blank(c)); + if (c == '!' || c == '?' || c == '%') + { register int k = 1; + if (c == '!') + { c = soap_get1(soap); + if (c == '[') + { do c = soap_get1(soap); + while ((int)c != EOF && c != '['); + if ((int)c == EOF) + break; + soap->cdata = 1; + c = soap_get1(soap); + continue; + } + if (c == '-' && (c = soap_get1(soap)) == '-') + { do + { c = soap_get1(soap); + if (c == '-' && (c = soap_get1(soap)) == '-') + break; + } while ((int)c != EOF); + } + } + else if (c == '?') + c = soap_get_pi(soap); + while ((int)c != EOF) + { if (c == '<') + k++; + else if (c == '>') + { if (--k <= 0) + break; + } + c = soap_get1(soap); + } + if ((int)c == EOF) + break; + c = soap_get1(soap); + continue; + } + if (c == '/') + return SOAP_TT; + soap_revget1(soap); + return SOAP_LT; + case '>': + return SOAP_GT; + case '"': + return SOAP_QT; + case '\'': + return SOAP_AP; + case '&': + return soap_char(soap) | 0x80000000; + } + break; + } + return c; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static soap_wchar +soap_get_pi(struct soap *soap) +{ char buf[64]; + register char *s = buf; + register int i = sizeof(buf); + register soap_wchar c = soap_getchar(soap); + /* This is a quick way to parse XML PI and we could use a callback instead to + * enable applications to intercept processing instructions */ + while ((int)c != EOF && c != '?') + { if (--i > 0) + { if (soap_blank(c)) + c = ' '; + *s++ = (char)c; + } + c = soap_getchar(soap); + } + *s = '\0'; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "XML PI \n", buf)); + if (!strncmp(buf, "xml ", 4)) + { s = strstr(buf, " encoding="); + if (s && s[10]) + { if (!soap_tag_cmp(s + 11, "iso-8859-1*") + || !soap_tag_cmp(s + 11, "latin1*")) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to latin1 encoding\n")); + soap->mode |= SOAP_ENC_LATIN; + } + else if (!soap_tag_cmp(s + 11, "utf-8*")) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to utf-8 encoding\n")); + soap->mode &= ~SOAP_ENC_LATIN; + } + } + } + if ((int)c != EOF) + c = soap_getchar(soap); + return c; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_move(struct soap *soap, long n) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving %ld bytes forward\n", (long)n)); + for (; n > 0; n--) + if ((int)soap_getchar(soap) == EOF) + return SOAP_EOF; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_tell(struct soap *soap) +{ return soap->count - soap->buflen + soap->bufidx - (soap->ahead != 0); +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_pututf8(struct soap *soap, register unsigned long c) +{ char tmp[16]; + if (c < 0x80 && c > 0) + { *tmp = (char)c; + return soap_send_raw(soap, tmp, 1); + } +#ifndef WITH_LEAN + if (c >= 0x80) + { register char *t = tmp; + if (c < 0x0800) + *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); + else + { if (c < 0x010000) + *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + else + { if (c < 0x200000) + *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + else + { if (c < 0x04000000) + *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + else + { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + } + *t++ = (char)(0x80 | (c & 0x3F)); + *t = '\0'; + } +#else + sprintf(tmp, "&#%lu;", c); +#endif + return soap_send(soap, tmp); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +soap_wchar +SOAP_FMAC2 +soap_getutf8(struct soap *soap) +{ register soap_wchar c, c1, c2, c3, c4; + c = soap->ahead; + if (c > 0xFF) + { soap->ahead = 0; + return c; + } +again: + c = soap_get(soap); + if (c < 0x80 || (soap->mode & SOAP_ENC_LATIN)) + return c; + c1 = soap_get1(soap); + if (c1 < 0x80) + { soap_revget1(soap); /* doesn't look like this is UTF8 */ + return c; + } + c1 &= 0x3F; + if (c < 0xE0) + return ((soap_wchar)(c & 0x1F) << 6) | c1; + c2 = (soap_wchar)soap_get1(soap) & 0x3F; + if (c == 0xEF && c1 == 0x3B && c2 == 0x3F) /* ignore UTF-8 BOM */ + goto again; + if (c < 0xF0) + return ((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2; + c3 = (soap_wchar)soap_get1(soap) & 0x3F; + if (c < 0xF8) + return ((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3; + c4 = (soap_wchar)soap_get1(soap) & 0x3F; + if (c < 0xFC) + return ((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4; + return ((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(soap_get1(soap) & 0x3F); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_puthex(struct soap *soap, const unsigned char *s, int n) +{ char d[2]; + register int i; +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { if (!(soap->dom->data = soap_s2hex(soap, s, NULL, n))) + return soap->error; + return SOAP_OK; + } +#endif + for (i = 0; i < n; i++) + { register int m = *s++; + d[0] = (char)((m >> 4) + (m > 159 ? '7' : '0')); + m &= 0x0F; + d[1] = (char)(m + (m > 9 ? '7' : '0')); + if (soap_send_raw(soap, d, 2)) + return soap->error; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +unsigned char* +SOAP_FMAC2 +soap_gethex(struct soap *soap, int *n) +{ +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { soap->dom->data = soap_string_in(soap, 0, -1, -1); + return (unsigned char*)soap_hex2s(soap, soap->dom->data, NULL, 0, n); + } +#endif +#ifdef WITH_FAST + soap->labidx = 0; + for (;;) + { register char *s; + register size_t i, k; + if (soap_append_lab(soap, NULL, 0)) + return NULL; + s = soap->labbuf + soap->labidx; + k = soap->lablen - soap->labidx; + soap->labidx = soap->lablen; + for (i = 0; i < k; i++) + { register char d1, d2; + register soap_wchar c; + c = soap_get(soap); + if (soap_isxdigit(c)) + { d1 = (char)c; + c = soap_get(soap); + if (soap_isxdigit(c)) + d2 = (char)c; + else + { soap->error = SOAP_TYPE; + return NULL; + } + } + else + { unsigned char *p; + soap_unget(soap, c); + if (n) + *n = (int)(soap->lablen + i - k); + p = (unsigned char*)soap_malloc(soap, soap->lablen + i - k); + if (p) + memcpy(p, soap->labbuf, soap->lablen + i - k); + return p; + } + *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'); + } + } +#else + if (soap_new_block(soap)) + return NULL; + for (;;) + { register int i; + register char *s = (char*)soap_push_block(soap, SOAP_BLKLEN); + if (!s) + { soap_end_block(soap); + return NULL; + } + for (i = 0; i < SOAP_BLKLEN; i++) + { register char d1, d2; + register soap_wchar c = soap_get(soap); + if (soap_isxdigit(c)) + { d1 = (char)c; + c = soap_get(soap); + if (soap_isxdigit(c)) + d2 = (char)c; + else + { soap_end_block(soap); + soap->error = SOAP_TYPE; + return NULL; + } + } + else + { unsigned char *p; + soap_unget(soap, c); + if (n) + *n = (int)soap_size_block(soap, i); + p = (unsigned char*)soap_save_block(soap, NULL, 0); + return p; + } + *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'); + } + } +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putbase64(struct soap *soap, const unsigned char *s, int n) +{ register int i; + register unsigned long m; + char d[4]; + if (!s) + return SOAP_OK; +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { if (!(soap->dom->data = soap_s2base64(soap, s, NULL, n))) + return soap->error; + return SOAP_OK; + } +#endif + for (; n > 2; n -= 3, s += 3) + { m = s[0]; + m = (m << 8) | s[1]; + m = (m << 8) | s[2]; + for (i = 4; i > 0; m >>= 6) + d[--i] = soap_base64o[m & 0x3F]; + if (soap_send_raw(soap, d, 4)) + return soap->error; + } + if (n > 0) + { m = 0; + for (i = 0; i < n; i++) + m = (m << 8) | *s++; + for (; i < 3; i++) + m <<= 8; + for (i++; i > 0; m >>= 6) + d[--i] = soap_base64o[m & 0x3F]; + for (i = 3; i > n; i--) + d[i] = '='; + if (soap_send_raw(soap, d, 4)) + return soap->error; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +unsigned char* +SOAP_FMAC2 +soap_getbase64(struct soap *soap, int *n, int malloc_flag) +{ +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { soap->dom->data = soap_string_in(soap, 0, -1, -1); + return (unsigned char*)soap_base642s(soap, soap->dom->data, NULL, 0, n); + } +#endif +#ifdef WITH_FAST + soap->labidx = 0; + for (;;) + { register size_t i, k; + register char *s; + if (soap_append_lab(soap, NULL, 2)) + return NULL; + s = soap->labbuf + soap->labidx; + k = soap->lablen - soap->labidx; + soap->labidx = 3 * (soap->lablen / 3); + if (!s) + return NULL; + if (k > 2) + { for (i = 0; i < k - 2; i += 3) + { register unsigned long m = 0; + register int j = 0; + do + { register soap_wchar c = soap_get(soap); + if (c == '=' || c < 0) + { unsigned char *p; + switch (j) + { case 2: + *s++ = (char)((m >> 4) & 0xFF); + i++; + break; + case 3: + *s++ = (char)((m >> 10) & 0xFF); + *s++ = (char)((m >> 2) & 0xFF); + i += 2; + } + if (n) + *n = (int)(soap->lablen + i - k); + p = (unsigned char*)soap_malloc(soap, soap->lablen + i - k); + if (p) + memcpy(p, soap->labbuf, soap->lablen + i - k); + if (c >= 0) + { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT) + ; + } + soap_unget(soap, c); + return p; + } + c -= '+'; + if (c >= 0 && c <= 79) + { register int b = soap_base64i[c]; + if (b >= 64) + { soap->error = SOAP_TYPE; + return NULL; + } + m = (m << 6) + b; + j++; + } + else if (!soap_blank(c + '+')) + { soap->error = SOAP_TYPE; + return NULL; + } + } while (j < 4); + *s++ = (char)((m >> 16) & 0xFF); + *s++ = (char)((m >> 8) & 0xFF); + *s++ = (char)(m & 0xFF); + } + } + } +#else + if (soap_new_block(soap)) + return NULL; + for (;;) + { register int i; + register char *s = (char*)soap_push_block(soap, 3 * SOAP_BLKLEN); /* must be multiple of 3 */ + if (!s) + { soap_end_block(soap); + return NULL; + } + for (i = 0; i < SOAP_BLKLEN; i++) + { register unsigned long m = 0; + register int j = 0; + do + { register soap_wchar c = soap_get(soap); + if (c == '=' || c < 0) + { unsigned char *p; + i *= 3; + switch (j) + { case 2: + *s++ = (char)((m >> 4) & 0xFF); + i++; + break; + case 3: + *s++ = (char)((m >> 10) & 0xFF); + *s++ = (char)((m >> 2) & 0xFF); + i += 2; + } + if (n) + *n = (int)soap_size_block(soap, i); + p = (unsigned char*)soap_save_block(soap, NULL, 0); + if (c >= 0) + { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT) + ; + } + soap_unget(soap, c); + return p; + } + c -= '+'; + if (c >= 0 && c <= 79) + { int b = soap_base64i[c]; + if (b >= 64) + { soap->error = SOAP_TYPE; + return NULL; + } + m = (m << 6) + b; + j++; + } + else if (!soap_blank(c)) + { soap->error = SOAP_TYPE; + return NULL; + } + } while (j < 4); + *s++ = (char)((m >> 16) & 0xFF); + *s++ = (char)((m >> 8) & 0xFF); + *s++ = (char)(m & 0xFF); + } + } +#endif +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_xop_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options) +{ /* Check MTOM xop:Include element (within hex/base64Binary) */ + /* TODO: this code to be obsoleted with new import/xop.h conventions */ + int body = soap->body; /* should save type too? */ + if (!soap_peek_element(soap)) + { if (!soap_element_begin_in(soap, "xop:Include", 0, NULL) && *soap->href) + { if (soap_dime_forward(soap, ptr, size, id, type, options)) + return soap->error; + } + if (soap->body && soap_element_end_in(soap, NULL)) + return soap->error; + } + soap->body = body; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_dime_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options) +{ struct soap_xlist *xp; + *ptr = NULL; + *size = 0; + *id = NULL; + *type = NULL; + *options = NULL; + if (!*soap->href) + return SOAP_OK; + *id = soap_strdup(soap, soap->href); + xp = (struct soap_xlist*)SOAP_MALLOC(soap, sizeof(struct soap_xlist)); + if (!xp) + return soap->error = SOAP_EOM; + xp->next = soap->xlist; + xp->ptr = ptr; + xp->size = size; + xp->id = *id; + xp->type = type; + xp->options = options; + soap->xlist = xp; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_strdup(struct soap *soap, const char *s) +{ char *t = NULL; + if (s && (t = (char*)soap_malloc(soap, strlen(s) + 1))) + strcpy(t, s); + return t; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +wchar_t * +SOAP_FMAC2 +soap_wstrdup(struct soap *soap, const wchar_t *s) +{ wchar_t *t = NULL; + if (s) + { size_t n = 0; + while (s[n]) + n++; + if ((t = (wchar_t*)soap_malloc(soap, sizeof(wchar_t)*(n+1)))) + memcpy(t, s, sizeof(wchar_t)*(n+1)); + } + return t; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_new_block(struct soap *soap) +{ struct soap_blist *p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New block sequence (prev=%p)\n", soap->blist)); + if (!(p = (struct soap_blist*)SOAP_MALLOC(soap, sizeof(struct soap_blist)))) + return SOAP_EOM; + p->next = soap->blist; + p->ptr = NULL; + p->size = 0; + soap->blist = p; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_push_block(struct soap *soap, size_t n) +{ char *p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push block of %u bytes (%u bytes total)\n", (unsigned int)n, (unsigned int)soap->blist->size + (unsigned int)n)); + if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(char*) + sizeof(size_t)))) + { soap->error = SOAP_EOM; + return NULL; + } + *(char**)p = soap->blist->ptr; + *(size_t*)(p + sizeof(char*)) = n; + soap->blist->ptr = p; + soap->blist->size += n; + return p + sizeof(char*) + sizeof(size_t); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_pop_block(struct soap *soap) +{ char *p; + if (!soap->blist->ptr) + return; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop block\n")); + p = soap->blist->ptr; + soap->blist->size -= *(size_t*)(p + sizeof(char*)); + soap->blist->ptr = *(char**)p; + SOAP_FREE(soap, p); +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static void +soap_update_ptrs(struct soap *soap, char *start, char *end, char *p1, char *p2) +{ int i; + register struct soap_ilist *ip = NULL; + register struct soap_flist *fp = NULL; +#ifndef WITH_LEANER + register struct soap_xlist *xp = NULL; +#endif + register void *p, **q; + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { if (ip->ptr && (char*)ip->ptr >= start && (char*)ip->ptr < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", ip->id, ip->ptr, (char*)ip->ptr + (p1-p2))); + ip->ptr = (char*)ip->ptr + (p1-p2); + } + for (q = &ip->link; q; q = (void**)p) + { p = *q; + if (p && (char*)p >= start && (char*)p < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Link update id='%s' %p\n", ip->id, p)); + *q = (char*)p + (p1-p2); + } + } + for (q = &ip->copy; q; q = (void**)p) + { p = *q; + if (p && (char*)p >= start && (char*)p < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy chain update id='%s' %p\n", ip->id, p)); + *q = (char*)p + (p1-p2); + } + } + for (fp = ip->flist; fp; fp = fp->next) + { if ((char*)fp->ptr >= start && (char*)fp->ptr < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy list update id='%s' %p\n", ip->id, fp)); + fp->ptr = (char*)fp->ptr + (p1-p2); + } + } + } + } +#ifndef WITH_LEANER + for (xp = soap->xlist; xp; xp = xp->next) + { if (xp->ptr && (char*)xp->ptr >= start && (char*)xp->ptr < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", xp->id?xp->id:"", xp->ptr, (char*)xp->ptr + (p1-p2))); + xp->ptr = (unsigned char**)((char*)xp->ptr + (p1-p2)); + xp->size = (int*)((char*)xp->size + (p1-p2)); + xp->type = (char**)((char*)xp->type + (p1-p2)); + xp->options = (char**)((char*)xp->options + (p1-p2)); + } + } +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static int +soap_has_copies(struct soap *soap, register const char *start, register const char *end) +{ register int i; + register struct soap_ilist *ip = NULL; + register struct soap_flist *fp = NULL; + register const char *p; + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { for (p = (const char*)ip->copy; p; p = *(const char**)p) + if (p >= start && p < end) + return SOAP_ERR; + for (fp = ip->flist; fp; fp = fp->next) + if ((const char*)fp->ptr >= start && (const char*)fp->ptr < end) + return SOAP_ERR; + } + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_resolve(struct soap *soap) +{ register int i; + register struct soap_ilist *ip = NULL; + register struct soap_flist *fp = NULL; + short flag; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data\n")); + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { if (ip->ptr) + { register void *p, **q, *r; + q = (void**)ip->link; + ip->link = NULL; + r = ip->ptr; + DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing link chain to resolve id='%s'\n", ip->id)); + while (q) + { p = *q; + *q = r; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "... link %p -> %p\n", q, r)); + q = (void**)p; + } + } + else if (*ip->id == '#') + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Missing data for id='%s'\n", ip->id)); + strcpy(soap->id, ip->id + 1); + return soap->error = SOAP_MISSING_ID; + } + } + } + do + { flag = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution phase\n")); + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { if (ip->ptr && !soap_has_copies(soap, (const char*)ip->ptr, (const char*)ip->ptr + ip->size)) + { if (ip->copy) + { register void *p, **q = (void**)ip->copy; + DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing copy chain to resolve id='%s'\n", ip->id)); + ip->copy = NULL; + do + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... copy %p -> %p (%u bytes)\n", ip->ptr, q, (unsigned int)ip->size)); + p = *q; + memcpy(q, ip->ptr, ip->size); + q = (void**)p; + } while (q); + flag = 1; + } + for (fp = ip->flist; fp; fp = ip->flist) + { register unsigned int k = fp->level; + register void *p = ip->ptr; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data type=%d location=%p level=%u,%u id='%s'\n", ip->type, p, ip->level, fp->level, ip->id)); + while (ip->level < k) + { register void **q = (void**)soap_malloc(soap, sizeof(void*)); + if (!q) + return soap->error; + *q = p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level, new location=%p holds=%p...\n", q, *q)); + p = (void*)q; + k--; + } + if (fp->fcopy) + fp->fcopy(soap, ip->type, fp->type, fp->ptr, fp->len, p, ip->size); + else + soap_fcopy(soap, ip->type, fp->type, fp->ptr, fp->len, p, ip->size); + ip->flist = fp->next; + SOAP_FREE(soap, fp); + flag = 1; + } + } + } + } + } while (flag); +#ifdef SOAP_DEBUG + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { if (ip->copy || ip->flist) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution error: forwarded data for id='%s' could not be propagated, please report this problem to the developers\n", ip->id)); + } + } + } +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution done\n")); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_size_block(struct soap *soap, size_t n) +{ if (soap->blist->ptr) + { soap->blist->size -= *(size_t*)(soap->blist->ptr + sizeof(char*)) - n; + *(size_t*)(soap->blist->ptr + sizeof(char*)) = n; + } + return soap->blist->size; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_first_block(struct soap *soap) +{ char *p, *q, *r; + p = soap->blist->ptr; + if (!p) + return NULL; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "First block\n")); + r = NULL; + do + { q = *(char**)p; + *(char**)p = r; + r = p; + p = q; + } while (p); + soap->blist->ptr = r; + return r + sizeof(char*) + sizeof(size_t); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_next_block(struct soap *soap) +{ char *p; + p = soap->blist->ptr; + if (p) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Next block\n")); + soap->blist->ptr = *(char**)p; + SOAP_FREE(soap, p); + if (soap->blist->ptr) + return soap->blist->ptr + sizeof(char*) + sizeof(size_t); + } + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_block_size(struct soap *soap) +{ return *(size_t*)(soap->blist->ptr + sizeof(char*)); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_end_block(struct soap *soap) +{ struct soap_blist *bp; + char *p, *q; + bp = soap->blist; + if (bp) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of block sequence, free all remaining blocks\n")); + for (p = bp->ptr; p; p = q) + { q = *(char**)p; + SOAP_FREE(soap, p); + } + soap->blist = bp->next; + SOAP_FREE(soap, bp); + } + DBGLOG(TEST, if (soap->blist) SOAP_MESSAGE(fdebug, "Restore previous block sequence\n")); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_save_block(struct soap *soap, char *p, int flag) +{ register size_t n; + register char *q, *s; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Save all blocks in contiguous memory space of %u bytes (%p->%p)\n", (unsigned int)soap->blist->size, soap->blist->ptr, p)); + if (soap->blist->size) + { if (!p) + p = (char*)soap_malloc(soap, soap->blist->size); + if (p) + { for (s = p, q = soap_first_block(soap); q; q = soap_next_block(soap)) + { n = soap_block_size(soap); +#ifndef WITH_NOIDREF + if (flag) + soap_update_ptrs(soap, q, q + n, s, q); +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy %u bytes from %p to %p\n", (unsigned int)n, q, s)); + memcpy(s, q, n); + s += n; + } + } + else + soap->error = SOAP_EOM; + } + soap_end_block(soap); + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putsize(struct soap *soap, const char *type, int size) +{ return soap_putsizes(soap, type, &size, 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putsizes(struct soap *soap, const char *type, const int *size, int dim) +{ return soap_putsizesoffsets(soap, type, size, NULL, dim); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putsizesoffsets(struct soap *soap, const char *type, const int *size, const int *offset, int dim) +{ int i; + if (!type) + return NULL; + if (soap->version == 2) + { sprintf(soap->type, "%s[%d", type, size[0]); + for (i = 1; i < dim; i++) + sprintf(soap->type + strlen(soap->type), " %d", size[i]); + } + else + { if (offset) + { sprintf(soap->type, "%s[%d", type, size[0] + offset[0]); + for (i = 1; i < dim; i++) + sprintf(soap->type + strlen(soap->type), ",%d", size[i] + offset[i]); + } + else + { sprintf(soap->type, "%s[%d", type, size[0]); + for (i = 1; i < dim; i++) + sprintf(soap->type + strlen(soap->type), ",%d", size[i]); + } + strcat(soap->type, "]"); + } + return soap->type; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putoffset(struct soap *soap, int offset) +{ return soap_putoffsets(soap, &offset, 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putoffsets(struct soap *soap, const int *offset, int dim) +{ register int i; + sprintf(soap->arrayOffset, "[%d", offset[0]); + for (i = 1; i < dim; i++) + sprintf(soap->arrayOffset + strlen(soap->arrayOffset), ",%d", offset[i]); + strcat(soap->arrayOffset, "]"); + return soap->arrayOffset; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_size(const int *size, int dim) +{ register int i, n = size[0]; + for (i = 1; i < dim; i++) + n *= size[i]; + return n; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getoffsets(const char *attr, const int *size, int *offset, int dim) +{ register int i, j = 0; + if (offset) + for (i = 0; i < dim && attr && *attr; i++) + { attr++; + j *= size[i]; + j += offset[i] = (int)atol(attr); + attr = strchr(attr, ','); + } + else + for (i = 0; i < dim && attr && *attr; i++) + { attr++; + j *= size[i]; + j += (int)atol(attr); + attr = strchr(attr, ','); + } + return j; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getsize(const char *attr1, const char *attr2, int *j) +{ register int n, k; + char *s; + *j = 0; + if (!*attr1) + return -1; + if (*attr1 == '[') + attr1++; + n = 1; + for (;;) + { k = (int)soap_strtol(attr1, &s, 10); + n *= k; + if (k < 0 || n > SOAP_MAXARRAYSIZE || s == attr1) + return -1; + attr1 = strchr(s, ','); + if (!attr1) + attr1 = strchr(s, ' '); + if (attr2 && *attr2) + { attr2++; + *j *= k; + k = (int)soap_strtol(attr2, &s, 10); + *j += k; + if (k < 0) + return -1; + attr2 = s; + } + if (!attr1) + break; + attr1++; + } + return n - *j; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getsizes(const char *attr, int *size, int dim) +{ register int i, k, n; + if (!*attr) + return -1; + i = (int)strlen(attr); + n = 1; + do + { for (i = i-1; i >= 0; i--) + if (attr[i] == '[' || attr[i] == ',' || attr[i] == ' ') + break; + k = (int)atol(attr + i + 1); + n *= size[--dim] = k; + if (k < 0 || n > SOAP_MAXARRAYSIZE) + return -1; + } while (i >= 0 && attr[i] != '['); + return n; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getposition(const char *attr, int *pos) +{ register int i, n; + if (!*attr) + return -1; + n = 0; + i = 1; + do + { pos[n++] = (int)atol(attr + i); + while (attr[i] && attr[i] != ',' && attr[i] != ']') + i++; + if (attr[i] == ',') + i++; + } while (n < SOAP_MAXDIMS && attr[i] && attr[i] != ']'); + return n; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_push_namespace(struct soap *soap, const char *id, const char *ns) +{ register struct soap_nlist *np; + register struct Namespace *p; + register short i = -1; + register size_t n, k; + n = strlen(id); + k = strlen(ns) + 1; + p = soap->local_namespaces; + if (p) + { for (i = 0; p->id; p++, i++) + { if (p->ns && !strcmp(ns, p->ns)) + { if (p->out) + { SOAP_FREE(soap, p->out); + p->out = NULL; + } + break; + } + if (p->out) + { if (!strcmp(ns, p->out)) + break; + } + else if (p->in) + { if (!soap_tag_cmp(ns, p->in)) + { if ((p->out = (char*)SOAP_MALLOC(soap, k))) + strcpy(p->out, ns); + break; + } + } + } + if (!p || !p->id) + i = -1; + } + if (i >= 0) + k = 0; + np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k); + if (!np) + return soap->error = SOAP_EOM; + np->next = soap->nlist; + soap->nlist = np; + np->level = soap->level; + np->index = i; + strcpy(np->id, id); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push namespace binding (level=%u) '%s' '%s'\n", soap->level, id, ns)); + if (i < 0) + { np->ns = np->id + n + 1; + strcpy(np->ns, ns); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push NOT OK: no match found for '%s' in namespace mapping table (added to stack anyway)\n", ns)); + } + else + { np->ns = NULL; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push OK ('%s' matches '%s' in namespace table)\n", id, p->id)); + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_pop_namespace(struct soap *soap) +{ register struct soap_nlist *np, *nq; + for (np = soap->nlist; np && np->level >= soap->level; np = nq) + { nq = np->next; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop namespace binding (level=%u) '%s'\n", soap->level, np->id)); + SOAP_FREE(soap, np); + } + soap->nlist = np; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_match_namespace(struct soap *soap, const char *id1, const char *id2, size_t n1, size_t n2) +{ register struct soap_nlist *np = soap->nlist; + while (np && (strncmp(np->id, id1, n1) || np->id[n1])) + np = np->next; + if (np) + { if (np->index < 0 + || (soap->local_namespaces[np->index].id + && (strncmp(soap->local_namespaces[np->index].id, id2, n2) + || soap->local_namespaces[np->index].id[n2]))) + return SOAP_NAMESPACE; + return SOAP_OK; + } + if (n1 == 3 && n1 == n2 && !strncmp(id1, "xml", 3) && !strncmp(id1, id2, 3)) + return SOAP_OK; + return soap->error = SOAP_SYNTAX_ERROR; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_current_namespace(struct soap *soap, const char *tag) +{ register struct soap_nlist *np; + register const char *s; + if (!tag || !strncmp(tag, "xml", 3)) + return NULL; + np = soap->nlist; + if (!(s = strchr(tag, ':'))) + { while (np && *np->id) /* find default namespace, if present */ + np = np->next; + } + else + { while (np && (strncmp(np->id, tag, s - tag) || np->id[s - tag])) + np = np->next; + if (!np) + soap->error = SOAP_NAMESPACE; + } + if (np) + { if (np->index >= 0) + return soap->namespaces[np->index].ns; + if (np->ns) + return soap_strdup(soap, np->ns); + } + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_tag_cmp(const char *s, const char *t) +{ for (;;) + { register int c1 = *s; + register int c2 = *t; + if (!c1 || c1 == '"') + break; + if (c2 != '-') + { if (c1 != c2) + { if (c1 >= 'A' && c1 <= 'Z') + c1 += 'a' - 'A'; + if (c2 >= 'A' && c2 <= 'Z') + c2 += 'a' - 'A'; + } + if (c1 != c2) + { if (c2 != '*') + return 1; + c2 = *++t; + if (!c2) + return 0; + if (c2 >= 'A' && c2 <= 'Z') + c2 += 'a' - 'A'; + for (;;) + { c1 = *s; + if (!c1 || c1 == '"') + break; + if (c1 >= 'A' && c1 <= 'Z') + c1 += 'a' - 'A'; + if (c1 == c2 && !soap_tag_cmp(s + 1, t + 1)) + return 0; + s++; + } + break; + } + } + s++; + t++; + } + if (*t == '*' && !t[1]) + return 0; + return *t; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_match_tag(struct soap *soap, const char *tag1, const char *tag2) +{ register const char *s, *t; + register int err; + if (!tag1 || !tag2 || !*tag2) + return SOAP_OK; + s = strchr(tag1, ':'); + t = strchr(tag2, ':'); + if (t) + { if (s) + { if (t[1] && SOAP_STRCMP(s + 1, t + 1)) + return SOAP_TAG_MISMATCH; + if (t != tag2 && (err = soap_match_namespace(soap, tag1, tag2, s - tag1, t - tag2))) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2)); + if (err == SOAP_NAMESPACE) + return SOAP_TAG_MISMATCH; + return err; + } + } + else if (SOAP_STRCMP(tag1, t + 1)) + { return SOAP_TAG_MISMATCH; + } + else if (t != tag2 && (err = soap_match_namespace(soap, tag1, tag2, 0, t - tag2))) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2)); + if (err == SOAP_NAMESPACE) + return SOAP_TAG_MISMATCH; + return err; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags and (default) namespaces match: '%s' '%s'\n", tag1, tag2)); + return SOAP_OK; + } + if (s) + { if (SOAP_STRCMP(s + 1, tag2)) + return SOAP_TAG_MISMATCH; + } + else if (SOAP_STRCMP(tag1, tag2)) + return SOAP_TAG_MISMATCH; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags match: '%s' '%s'\n", tag1, tag2)); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_match_array(struct soap *soap, const char *type) +{ if (*soap->arrayType) + if (soap_match_tag(soap, soap->arrayType, type) + && soap_match_tag(soap, soap->arrayType, "xsd:anyType") + && soap_match_tag(soap, soap->arrayType, "xsd:ur-type") + ) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array type mismatch: '%s' '%s'\n", soap->arrayType, type)); + return SOAP_TAG_MISMATCH; + } + return SOAP_OK; +} +#endif + +/******************************************************************************\ + * + * SSL + * +\******************************************************************************/ + +#ifdef WITH_OPENSSL +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_rand() +{ unsigned char buf[4]; + if (!soap_ssl_init_done) + soap_ssl_init(); + RAND_pseudo_bytes(buf, 4); + return *(int*)buf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_ssl_server_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *password, const char *cafile, const char *capath, const char *dhfile, const char *randfile, const char *sid) +{ int err; + soap->keyfile = keyfile; + soap->password = password; + soap->cafile = cafile; + soap->capath = capath; + soap->dhfile = dhfile; + soap->randfile = randfile; + soap->ssl_flags = flags | (dhfile == NULL ? SOAP_SSL_RSA : 0); + if (!(err = soap->fsslauth(soap))) + { if (sid) + SSL_CTX_set_session_id_context(soap->ctx, (unsigned char*)sid, (unsigned int)strlen(sid)); + } + return err; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_ssl_client_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *password, const char *cafile, const char *capath, const char *randfile) +{ soap->keyfile = keyfile; + soap->password = password; + soap->cafile = cafile; + soap->capath = capath; + soap->dhfile = NULL; + soap->ssl_flags = flags; + soap->randfile = randfile; + return soap->fsslauth(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_ssl_init() +{ /* Note: for MT systems, the main program MUST call soap_ssl_init() before any threads are started */ + if (!soap_ssl_init_done) + { soap_ssl_init_done = 1; + SSL_library_init(); +#ifndef WITH_LEAN + SSL_load_error_strings(); +#endif + if (!RAND_load_file("/dev/urandom", 1024)) + { char buf[1024]; + RAND_seed(buf, sizeof(buf)); + while (!RAND_status()) + { int r = rand(); + RAND_seed(&r, sizeof(int)); + } + } + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +const char * +SOAP_FMAC2 +soap_ssl_error(struct soap *soap, int ret) +{ int err = SSL_get_error(soap->ssl, ret); + const char *msg = soap_code_str(h_ssl_error_codes, err); + if (msg) + strcpy(soap->msgbuf, msg); + else + return ERR_error_string(err, soap->msgbuf); + if (ERR_peek_error()) + { unsigned long r; + strcat(soap->msgbuf, "\n"); + while ((r = ERR_get_error())) + ERR_error_string_n(r, soap->msgbuf + strlen(soap->msgbuf), sizeof(soap->msgbuf) - strlen(soap->msgbuf)); + } + else + { switch (ret) + { case 0: + strcpy(soap->msgbuf, "EOF was observed that violates the protocol. The client probably provided invalid authentication information."); + break; + case -1: + sprintf(soap->msgbuf, "Error observed by underlying BIO: %s", strerror(errno)); + break; + } + } + return soap->msgbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +ssl_password(char *buf, int num, int rwflag, void *userdata) +{ if (num < (int)strlen((char*)userdata) + 1) + return 0; + return (int)strlen(strcpy(buf, (char*)userdata)); +} +#endif + +/******************************************************************************/ +/* This callback is included for future references. It should not be deleted +#ifndef PALM_2 +static DH * +ssl_tmp_dh(SSL *ssl, int is_export, int keylength) +{ static DH *dh512 = NULL; + static DH *dh1024 = NULL; + DH *dh; + switch (keylength) + { case 512: + if (!dh512) + { BIO *bio = BIO_new_file("dh512.pem", "r"); + if (bio) + { dh512 = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + return dh512; + } + } + else + return dh512; + default: + if (!dh1024) + { BIO *bio = BIO_new_file("dh1024.pem", "r"); + if (bio) + { dh1024 = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + } + } + dh = dh1024; + } + return dh; +} +#endif +*/ + +/******************************************************************************/ +#ifndef PALM_1 +static int +ssl_auth_init(struct soap *soap) +{ long flags; + int mode; + if (!soap_ssl_init_done) + soap_ssl_init(); + if (!soap->ctx) + { if (!(soap->ctx = SSL_CTX_new(SSLv23_method()))) + return soap_set_receiver_error(soap, "SSL error", "Can't setup context", SOAP_SSL_ERROR); + /* Alters the behavior of SSL read/write: + SSL_CTX_set_mode(soap->ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY); + */ + } + if (soap->randfile) + { if (!RAND_load_file(soap->randfile, -1)) + return soap_set_receiver_error(soap, "SSL error", "Can't load randomness", SOAP_SSL_ERROR); + } + if (soap->cafile || soap->capath) + { if (!SSL_CTX_load_verify_locations(soap->ctx, soap->cafile, soap->capath)) + return soap_set_receiver_error(soap, "SSL error", "Can't read CA file and directory", SOAP_SSL_ERROR); + if (soap->cafile && (soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION)) + SSL_CTX_set_client_CA_list(soap->ctx, SSL_load_client_CA_file(soap->cafile)); + } + if (!SSL_CTX_set_default_verify_paths(soap->ctx)) + return soap_set_receiver_error(soap, "SSL error", "Can't read default CA file and/or directory", SOAP_SSL_ERROR); +/* This code assumes a typical scenario, see alternative code below */ + if (soap->keyfile) + { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile)) + return soap_set_receiver_error(soap, "SSL error", "Can't read certificate key file", SOAP_SSL_ERROR); + if (soap->password) + { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password); + SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password); + } + if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM)) + return soap_set_receiver_error(soap, "SSL error", "Can't read key file", SOAP_SSL_ERROR); + } +/* Suggested alternative approach to check the key file for certs (cafile=NULL): + if (soap->password) + { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password); + SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password); + } + if (!soap->cafile || !SSL_CTX_use_certificate_chain_file(soap->ctx, soap->cafile)) + { if (soap->keyfile) + { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile)) + return soap_set_receiver_error(soap, "SSL error", "Can't read certificate or key file", SOAP_SSL_ERROR); + if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM)) + return soap_set_receiver_error(soap, "SSL error", "Can't read key file", SOAP_SSL_ERROR); + } + } +*/ + if ((soap->ssl_flags & SOAP_SSL_RSA)) + { RSA *rsa = RSA_generate_key(1024, RSA_F4, NULL, NULL); + if (!SSL_CTX_set_tmp_rsa(soap->ctx, rsa)) + { if (rsa) + RSA_free(rsa); + return soap_set_receiver_error(soap, "SSL error", "Can't set RSA key", SOAP_SSL_ERROR); + } + RSA_free(rsa); + } + else if (soap->dhfile) + { DH *dh = 0; + BIO *bio; + bio = BIO_new_file(soap->dhfile, "r"); + if (!bio) + return soap_set_receiver_error(soap, "SSL error", "Can't read DH file", SOAP_SSL_ERROR); + dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + if (SSL_CTX_set_tmp_dh(soap->ctx, dh) < 0) + { if (dh) + DH_free(dh); + return soap_set_receiver_error(soap, "SSL error", "Can't set DH parameters", SOAP_SSL_ERROR); + } + DH_free(dh); + } + flags = (SSL_OP_ALL | SSL_OP_NO_SSLv2); + if ((soap->ssl_flags & SOAP_SSLv3)) + flags |= SSL_OP_NO_TLSv1; + if ((soap->ssl_flags & SOAP_TLSv1)) + flags |= SSL_OP_NO_SSLv3; + SSL_CTX_set_options(soap->ctx, flags); + if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION)) + mode = (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT); + else if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION)) + mode = SSL_VERIFY_PEER; + else + mode = SSL_VERIFY_NONE; + SSL_CTX_set_verify(soap->ctx, mode, soap->fsslverify); +#if (OPENSSL_VERSION_NUMBER < 0x00905100L) + SSL_CTX_set_verify_depth(soap->ctx, 1); +#else + SSL_CTX_set_verify_depth(soap->ctx, 9); +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +ssl_verify_callback(int ok, X509_STORE_CTX *store) +{ +#ifdef SOAP_DEBUG + if (!ok) + { char data[256]; + X509 *cert = X509_STORE_CTX_get_current_cert(store); + fprintf(stderr, "SSL verify error or warning with certificate at depth %d: %s\n", X509_STORE_CTX_get_error_depth(store), X509_verify_cert_error_string(X509_STORE_CTX_get_error(store))); + X509_NAME_oneline(X509_get_issuer_name(cert), data, sizeof(data)); + fprintf(stderr, "certificate issuer %s\n", data); + X509_NAME_oneline(X509_get_subject_name(cert), data, sizeof(data)); + fprintf(stderr, "certificate subject %s\n", data); + } +#endif + /* Note: return 1 to continue, but unsafe progress will be terminated by SSL */ + return ok; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_ssl_accept(struct soap *soap) +{ BIO *bio; + int retries, r, s; + if (!soap_valid_socket(soap->socket)) + return soap_set_receiver_error(soap, "SSL error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR); + if (!soap->ctx && (soap->error = soap->fsslauth(soap))) + return SOAP_INVALID_SOCKET; + if (!soap->ssl) + { soap->ssl = SSL_new(soap->ctx); + if (!soap->ssl) + return soap_set_receiver_error(soap, "SSL error", "SSL_new() failed in soap_ssl_accept()", SOAP_SSL_ERROR); + } + else + SSL_clear(soap->ssl); + soap->imode |= SOAP_ENC_SSL; + soap->omode |= SOAP_ENC_SSL; + /* Set SSL sockets to non-blocking */ + SOAP_SOCKNONBLOCK(soap->socket) + bio = BIO_new_socket(soap->socket, BIO_NOCLOSE); + SSL_set_bio(soap->ssl, bio, bio); + retries = 100; /* 10 sec retries, 100 times 0.1 sec */ + while ((r = SSL_accept(soap->ssl)) <= 0) + { int err = SSL_get_error(soap->ssl, r); + if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) + { struct timeval timeout; + fd_set fd; +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + return SOAP_FD_EXCEEDED; /* Hint: MUST increase FD_SETSIZE */ +#endif + timeout.tv_sec = 0; + timeout.tv_usec = 100000; + FD_ZERO(&fd); + FD_SET(soap->socket, &fd); + if (err == SSL_ERROR_WANT_READ) + s = select((int)soap->socket + 1, &fd, NULL, &fd, &timeout); + else + s = select((int)soap->socket + 1, NULL, &fd, &fd, &timeout); + if (s < 0 && (s = soap_socket_errno(soap->socket)) != SOAP_EINTR) + { soap->errnum = s; + break; + } + } + else + { soap->errnum = err; + break; + } + if (retries-- <= 0) + break; + } + if (r <= 0) + { soap_set_receiver_error(soap, soap_ssl_error(soap, r), "SSL_accept() failed in soap_ssl_accept()", SOAP_SSL_ERROR); + soap_closesock(soap); + return SOAP_SSL_ERROR; + } + if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION)) + { X509 *peer; + int err; + if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK) + { soap_closesock(soap); + return soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL certificate presented by peer cannot be verified in soap_ssl_accept()", SOAP_SSL_ERROR); + } + peer = SSL_get_peer_certificate(soap->ssl); + if (!peer) + { soap_closesock(soap); + return soap_set_sender_error(soap, "SSL error", "No SSL certificate was presented by the peer in soap_ssl_accept()", SOAP_SSL_ERROR); + } + X509_free(peer); + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#endif /* WITH_OPENSSL */ + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_init(struct soap *soap) +{ soap->errmode = 1; +#ifdef WIN32 + if (tcp_done) + return 0; + else + { WSADATA w; + if (WSAStartup(MAKEWORD(1, 1), &w)) + return -1; + tcp_done = 1; + } +#endif + return 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_done(struct soap *soap) +{ +#ifdef SOAP_DEBUG + int i; +#endif + if (soap_check_state(soap)) + return; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Done with context\n")); + soap_free_temp(soap); + while (soap->clist) + { struct soap_clist *p = soap->clist->next; + SOAP_FREE(soap, soap->clist); + soap->clist = p; + } + soap->keep_alive = 0; /* to force close the socket */ + soap_closesock(soap); +#ifdef WITH_COOKIES + soap_free_cookies(soap); +#endif + while (soap->plugins) + { register struct soap_plugin *p = soap->plugins->next; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Removing plugin '%s'\n", soap->plugins->id)); + if (soap->plugins->fcopy || soap->state == SOAP_INIT) + soap->plugins->fdelete(soap, soap->plugins); + SOAP_FREE(soap, soap->plugins); + soap->plugins = p; + } + soap->fplugin = fplugin; + soap->fmalloc = NULL; +#ifndef WITH_NOHTTP + soap->fpost = http_post; + soap->fget = http_get; + soap->fput = http_put; + soap->fdel = http_del; + soap->fhead = http_head; + soap->fform = NULL; + soap->fposthdr = http_post_header; + soap->fresponse = http_response; + soap->fparse = http_parse; + soap->fparsehdr = http_parse_header; +#endif + soap->fheader = NULL; +#ifndef WITH_NOIO +#ifndef WITH_IPV6 + soap->fresolve = tcp_gethost; +#else + soap->fresolve = NULL; +#endif + soap->faccept = tcp_accept; + soap->fopen = tcp_connect; + soap->fclose = tcp_disconnect; + soap->fclosesocket = tcp_closesocket; + soap->fshutdownsocket = tcp_shutdownsocket; + soap->fsend = fsend; + soap->frecv = frecv; + soap->fpoll = soap_poll; +#else + soap->fopen = NULL; + soap->fclose = NULL; + soap->fpoll = NULL; +#endif +#ifndef WITH_LEANER + soap->fprepareinit = NULL; + soap->fpreparesend = NULL; + soap->fpreparerecv = NULL; + soap->fpreparefinal = NULL; +#endif + soap->fseterror = NULL; + soap->fignore = NULL; + soap->fserveloop = NULL; +#ifdef WITH_OPENSSL + if (soap->session) + { SSL_SESSION_free(soap->session); + soap->session = NULL; + } +#endif + if (soap->state == SOAP_INIT) + { if (soap_valid_socket(soap->master)) + { soap->fclosesocket(soap, soap->master); + soap->master = SOAP_INVALID_SOCKET; + } +#ifdef WITH_OPENSSL + if (soap->ctx) + { SSL_CTX_free(soap->ctx); + soap->ctx = NULL; + } +#endif + } +#ifdef WITH_ZLIB + if (soap->d_stream) + { SOAP_FREE(soap, (void*)soap->d_stream); + soap->d_stream = NULL; + } + if (soap->z_buf) + { SOAP_FREE(soap, (void*)soap->z_buf); + soap->z_buf = NULL; + } +#endif +#ifdef SOAP_DEBUG + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free logfiles\n")); + for (i = 0; i < SOAP_MAXLOGS; i++) + { if (soap->logfile[i]) + { SOAP_FREE(soap, (void*)soap->logfile[i]); + soap->logfile[i] = NULL; + } + soap_close_logfile(soap, i); + } + soap->state = 0; +#endif +#ifdef SOAP_MEM_DEBUG + soap_free_mht(soap); +#endif +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_cleanup(struct soap *soap) +{ soap_done(soap); +#ifdef WIN32 + if (!tcp_done) + return; + tcp_done = 0; + WSACleanup(); +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static const char* +tcp_error(struct soap *soap) +{ register const char *msg = NULL; + switch (soap->errmode) + { case 0: + msg = soap_strerror(soap); + break; + case 1: + msg = "WSAStartup failed"; + break; + case 2: + { +#ifndef WITH_LEAN + msg = soap_code_str(h_error_codes, soap->errnum); + if (!msg) +#endif + { sprintf(soap->msgbuf, "TCP/UDP IP error %d", soap->errnum); + msg = soap->msgbuf; + } + } + } + return msg; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static const char* +http_error(struct soap *soap, int status) +{ register const char *msg = SOAP_STR_EOS; +#ifndef WITH_LEAN + msg = soap_code_str(h_http_error_codes, status); + if (!msg) + msg = SOAP_STR_EOS; +#endif + return msg; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_IPV6 +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_gethost(struct soap *soap, const char *addr, struct in_addr *inaddr) +{ soap_int32 iadd = -1; + struct hostent hostent, *host = &hostent; +#ifdef VXWORKS + int hostint; + /* inet_addr(), and hostGetByName() expect "char *"; addr is a "const char *". */ + iadd = inet_addr((char*)addr); +#else +#if defined(_AIX43) || defined(TRU64) + struct hostent_data ht_data; +#endif +#ifdef AS400 + iadd = inet_addr((void*)addr); +#else + iadd = inet_addr(addr); +#endif +#endif + if (iadd != -1) + { memcpy(inaddr, &iadd, sizeof(iadd)); + return SOAP_OK; + } +#if defined(__GLIBC__) || (defined(HAVE_GETHOSTBYNAME_R) && (defined(FREEBSD) || defined(__FreeBSD__))) + if (gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &host, &soap->errnum) < 0) + host = NULL; +#elif defined(_AIX43) || defined(TRU64) + memset((void*)&ht_data, 0, sizeof(ht_data)); + if (gethostbyname_r(addr, &hostent, &ht_data) < 0) + { host = NULL; + soap->errnum = h_errno; + } +#elif defined(HAVE_GETHOSTBYNAME_R) + host = gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &soap->errnum); +#elif defined(VXWORKS) + /* If the DNS resolver library resolvLib has been configured in the vxWorks + * image, a query for the host IP address is sent to the DNS server, if the + * name was not found in the local host table. */ + hostint = hostGetByName((char*)addr); + if (hostint == ERROR) + { host = NULL; + soap->errnum = soap_errno; + } +#else +#ifdef AS400 + if (!(host = gethostbyname((void*)addr))) + soap->errnum = h_errno; +#else + if (!(host = gethostbyname(addr))) + soap->errnum = h_errno; +#endif +#endif + if (!host) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Host name not found\n")); + return SOAP_ERR; + } +#ifdef VXWORKS + inaddr->s_addr = hostint; +#else + memcpy(inaddr, host->h_addr, host->h_length); +#endif + return SOAP_OK; +} +#endif +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static SOAP_SOCKET +tcp_connect(struct soap *soap, const char *endpoint, const char *host, int port) +{ +#ifdef WITH_IPV6 + struct addrinfo hints, *res, *ressave; +#endif + SOAP_SOCKET fd; + int err = 0; +#ifndef WITH_LEAN + int retry = 10; + int len = SOAP_BUFLEN; + int set = 1; +#endif + if (soap_valid_socket(soap->socket)) + soap->fclosesocket(soap, soap->socket); + soap->socket = SOAP_INVALID_SOCKET; + if (tcp_init(soap)) + { soap->errnum = 0; + soap_set_sender_error(soap, tcp_error(soap), "TCP init failed in tcp_connect()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + soap->errmode = 0; +#ifdef WITH_IPV6 + memset((void*)&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; +#ifndef WITH_LEAN + if ((soap->omode & SOAP_IO_UDP)) + hints.ai_socktype = SOCK_DGRAM; + else +#endif + hints.ai_socktype = SOCK_STREAM; + soap->errmode = 2; + if (soap->proxy_host) + err = getaddrinfo(soap->proxy_host, soap_int2s(soap, soap->proxy_port), &hints, &res); + else + err = getaddrinfo(host, soap_int2s(soap, port), &hints, &res); + if (err) + { soap_set_sender_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in tcp_connect()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + ressave = res; +again: + fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + soap->errmode = 0; +#else +#ifndef WITH_LEAN +again: +#endif +#ifndef WITH_LEAN + if ((soap->omode & SOAP_IO_UDP)) + fd = socket(AF_INET, SOCK_DGRAM, 0); + else +#endif + fd = socket(AF_INET, SOCK_STREAM, 0); +#endif + if (!soap_valid_socket(fd)) + { +#ifdef WITH_IPV6 + if (res->ai_next) + { res = res->ai_next; + goto again; + } +#endif + soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "socket failed in tcp_connect()", SOAP_TCP_ERROR); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } +#ifdef SOCKET_CLOSE_ON_EXEC +#ifdef WIN32 +#ifndef UNDER_CE + SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0); +#endif +#else + fcntl(fd, F_SETFD, 1); +#endif +#endif +#ifndef WITH_LEAN + if (soap->connect_flags == SO_LINGER) + { struct linger linger; + memset((void*)&linger, 0, sizeof(linger)); + linger.l_onoff = 1; + linger.l_linger = 0; + if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger))) + { soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } + } + else if (soap->connect_flags && setsockopt(fd, SOL_SOCKET, soap->connect_flags, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "setsockopt failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } + if ((soap->keep_alive || soap->tcp_keep_alive) && setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } + if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } + if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } +#ifdef TCP_KEEPIDLE + if (soap->tcp_keep_idle && setsockopt((SOAP_SOCKET)fd, IPPROTO_TCP, TCP_KEEPIDLE, (unsigned int*)&(soap->tcp_keep_idle), sizeof(int))) + { soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPIDLE failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } +#endif +#ifdef TCP_KEEPINTVL + if (soap->tcp_keep_intvl && setsockopt((SOAP_SOCKET)fd, IPPROTO_TCP, TCP_KEEPINTVL, (unsigned int*)&(soap->tcp_keep_intvl), sizeof(int))) + { soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPINTVL failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } +#endif +#ifdef TCP_KEEPCNT + if (soap->tcp_keep_cnt && setsockopt((SOAP_SOCKET)fd, IPPROTO_TCP, TCP_KEEPCNT, (unsigned int*)&(soap->tcp_keep_cnt), sizeof(int))) + { soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPCNT failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } +#endif +#ifdef TCP_NODELAY + if (!(soap->omode & SOAP_IO_UDP) && setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } +#endif +#endif + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Opening socket %d to host='%s' port=%d\n", fd, host, port)); +#ifndef WITH_IPV6 + soap->peerlen = sizeof(soap->peer); + memset((void*)&soap->peer, 0, sizeof(soap->peer)); + soap->peer.sin_family = AF_INET; + soap->errmode = 2; + if (soap->proxy_host) + { if (soap->fresolve(soap, soap->proxy_host, &soap->peer.sin_addr)) + { soap_set_sender_error(soap, tcp_error(soap), "get proxy host by name failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } + soap->peer.sin_port = htons((short)soap->proxy_port); + } + else + { if (soap->fresolve(soap, host, &soap->peer.sin_addr)) + { soap_set_sender_error(soap, tcp_error(soap), "get host by name failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } + soap->peer.sin_port = htons((short)port); + } + soap->errmode = 0; +#ifndef WITH_LEAN + if ((soap->omode & SOAP_IO_UDP)) + { +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return fd; + } +#endif +#endif +#ifndef WITH_LEAN + if (soap->connect_timeout) + SOAP_SOCKNONBLOCK(fd) + else + SOAP_SOCKBLOCK(fd) +#endif + for (;;) + { +#ifdef WITH_IPV6 + if (connect(fd, res->ai_addr, (int)res->ai_addrlen)) +#else + if (connect(fd, (struct sockaddr*)&soap->peer, sizeof(soap->peer))) +#endif + { err = soap_socket_errno(fd); +#ifndef WITH_LEAN + if (err == SOAP_EADDRINUSE) + { soap->fclosesocket(soap, fd); + if (retry-- > 0) + goto again; + } + else if (soap->connect_timeout && (err == SOAP_EINPROGRESS || err == SOAP_EAGAIN || err == SOAP_EWOULDBLOCK)) + { + SOAP_SOCKLEN_T k; +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + { soap->error = SOAP_FD_EXCEEDED; +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; /* Hint: MUST increase FD_SETSIZE */ + } +#endif + for (;;) + { struct timeval timeout; + fd_set fds; + register int r; + if (soap->connect_timeout > 0) + { timeout.tv_sec = soap->connect_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->connect_timeout/1000000; + timeout.tv_usec = -soap->connect_timeout%1000000; + } + FD_ZERO(&fds); + FD_SET(fd, &fds); + r = select((int)fd + 1, NULL, &fds, NULL, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n")); + soap_set_sender_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } + r = soap_socket_errno(fd); + if (r != SOAP_EINTR) + { soap->errnum = r; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); + soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } + } + k = (SOAP_SOCKLEN_T)sizeof(soap->errnum); + if (!getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*)&soap->errnum, &k) && !soap->errnum) /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */ + break; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); + if (!soap->errnum) + soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } +#endif +#ifdef WITH_IPV6 + if (res->ai_next) + { res = res->ai_next; + soap->fclosesocket(soap, fd); + goto again; + } +#endif + if (err && err != SOAP_EINTR) + { soap->errnum = err; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); + soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } + } + else + break; + } +#ifdef WITH_IPV6 + soap->peerlen = 0; /* IPv6: already connected so use send() */ + freeaddrinfo(ressave); +#endif +#ifndef WITH_LEAN + if (soap->recv_timeout || soap->send_timeout) + SOAP_SOCKNONBLOCK(fd) + else + SOAP_SOCKBLOCK(fd) +#endif + soap->socket = fd; + soap->imode &= ~SOAP_ENC_SSL; + soap->omode &= ~SOAP_ENC_SSL; + if (!soap_tag_cmp(endpoint, "https:*")) + { +#ifdef WITH_OPENSSL + BIO *bio; + int r; + if (soap->proxy_host) + { unsigned int k = soap->omode; /* make sure we only parse HTTP */ + size_t n = soap->count; /* save the content length */ + char *userid, *passwd; + soap->omode &= ~SOAP_ENC; /* mask IO and ENC */ + soap->omode |= SOAP_IO_BUFFER; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connecting to %s proxy server\n", soap->proxy_http_version)); + sprintf(soap->tmpbuf, "CONNECT %s:%d HTTP/%s", host, port, soap->proxy_http_version); + if (soap_begin_send(soap) + || (soap->error = soap->fposthdr(soap, soap->tmpbuf, NULL))) + { soap->fclosesocket(soap, fd); + return SOAP_INVALID_SOCKET; + } +#ifndef WITH_LEAN + if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761) + { sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd); + strcpy(soap->tmpbuf, "Basic "); + soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262)); + if ((soap->error = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf))) + { soap->fclosesocket(soap, fd); + return soap->error; + } + } +#endif + if ((soap->error = soap->fposthdr(soap, NULL, NULL)) + || soap_flush(soap)) + { soap->fclosesocket(soap, fd); + return SOAP_INVALID_SOCKET; + } + soap->omode = k; + k = soap->imode; + soap->imode &= ~SOAP_ENC; /* mask IO and ENC */ + userid = soap->userid; /* preserve */ + passwd = soap->passwd; /* preserve */ + if ((soap->error = soap->fparse(soap))) + { soap->fclosesocket(soap, fd); + return SOAP_INVALID_SOCKET; + } + soap->userid = userid; /* restore */ + soap->passwd = passwd; /* restore */ + soap->imode = k; /* restore */ + soap->count = n; /* restore */ + if (soap_begin_send(soap)) + { soap->fclosesocket(soap, fd); + return SOAP_INVALID_SOCKET; + } + if (endpoint) + strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint)-1); /* restore */ + } + if (!soap->ctx && (soap->error = soap->fsslauth(soap))) + { soap_set_sender_error(soap, "SSL error", "SSL authentication failed in tcp_connect(): check password, key file, and ca file.", SOAP_SSL_ERROR); + soap->fclosesocket(soap, fd); + return SOAP_INVALID_SOCKET; + } + soap->ssl = SSL_new(soap->ctx); + if (!soap->ssl) + { soap->fclosesocket(soap, fd); + soap->error = SOAP_SSL_ERROR; + return SOAP_INVALID_SOCKET; + } + if (soap->session) + { if (!strcmp(soap->session_host, host) && soap->session_port == port) + SSL_set_session(soap->ssl, soap->session); + SSL_SESSION_free(soap->session); + soap->session = NULL; + } + soap->imode |= SOAP_ENC_SSL; + soap->omode |= SOAP_ENC_SSL; + bio = BIO_new_socket(fd, BIO_NOCLOSE); + SSL_set_bio(soap->ssl, bio, bio); +#ifndef WITH_LEAN + /* Connect timeout: set SSL sockets to non-blocking */ + if (soap->connect_timeout) + SOAP_SOCKNONBLOCK(fd) + else + SOAP_SOCKBLOCK(fd) + /* Try connecting until success or timeout */ + for (;;) + { if ((r = SSL_connect(soap->ssl)) <= 0) + { int err = SSL_get_error(soap->ssl, r); + if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) + { soap_set_sender_error(soap, soap_ssl_error(soap, r), "SSL connect failed in tcp_connect()", SOAP_SSL_ERROR); + soap->fclosesocket(soap, fd); + return SOAP_INVALID_SOCKET; + } + if (soap->connect_timeout) + { +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + { soap->error = SOAP_FD_EXCEEDED; + return SOAP_INVALID_SOCKET; /* Hint: MUST increase FD_SETSIZE */ + } +#endif + for (;;) + { struct timeval timeout; + fd_set fds; + register int r; + if (soap->connect_timeout > 0) + { timeout.tv_sec = soap->connect_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->connect_timeout/1000000; + timeout.tv_usec = -soap->connect_timeout%1000000; + } + FD_ZERO(&fds); + FD_SET(fd, &fds); + r = select((int)fd + 1, &fds, &fds, &fds, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n")); + soap_set_sender_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, fd); + return SOAP_INVALID_SOCKET; + } + } + continue; + } + } + break; + } + /* Set SSL sockets to nonblocking */ + SOAP_SOCKNONBLOCK(fd) +#endif + /* Check server credentials when required */ + if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION)) + { int err; + if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK) + { soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL certificate presented by peer cannot be verified in tcp_connect()", SOAP_SSL_ERROR); + soap->fclosesocket(soap, fd); + return SOAP_INVALID_SOCKET; + } + if (!(soap->ssl_flags & SOAP_SSL_SKIP_HOST_CHECK)) + { X509_NAME *subj; + int ext_count; + int ok = 0; + X509 *peer; + peer = SSL_get_peer_certificate(soap->ssl); + if (!peer) + { soap_set_sender_error(soap, "SSL error", "No SSL certificate was presented by the peer in tcp_connect()", SOAP_SSL_ERROR); + soap->fclosesocket(soap, fd); + return SOAP_INVALID_SOCKET; + } + ext_count = X509_get_ext_count(peer); + if (ext_count > 0) + { int i; + for (i = 0; i < ext_count; i++) + { X509_EXTENSION *ext = X509_get_ext(peer, i); + const char *ext_str = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext))); + if (ext_str && !strcmp(ext_str, "subjectAltName")) + { X509V3_EXT_METHOD *meth = X509V3_EXT_get(ext); + void *ext_data; +#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) + const unsigned char *data; +#else + unsigned char *data; +#endif + STACK_OF(CONF_VALUE) *val; + int j; + if (!meth) + break; + data = ext->value->data; +#if (OPENSSL_VERSION_NUMBER > 0x00907000L) + if (meth->it) + ext_data = ASN1_item_d2i(NULL, &data, ext->value->length, ASN1_ITEM_ptr(meth->it)); + else + { /* OpenSSL not perfectly portable at this point (?): + Some compilers appear to prefer + meth->d2i(NULL, (const unsigned char**)&data, ... + or + meth->d2i(NULL, &data, ext->value->length); + */ + ext_data = meth->d2i(NULL, &data, ext->value->length); + } +#else + ext_data = meth->d2i(NULL, &data, ext->value->length); +#endif + val = meth->i2v(meth, ext_data, NULL); + for (j = 0; j < sk_CONF_VALUE_num(val); j++) + { CONF_VALUE *nval = sk_CONF_VALUE_value(val, j); + if (nval && !strcmp(nval->name, "DNS") && !strcmp(nval->value, host)) + { ok = 1; + break; + } + } + } + if (ok) + break; + } + } + if (!ok && (subj = X509_get_subject_name(peer))) + { int i = -1; + do + { ASN1_STRING *name; + i = X509_NAME_get_index_by_NID(subj, NID_commonName, i); + if (i == -1) + break; + name = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subj, i)); + if (name) + { if (!soap_tag_cmp(host, (const char*)name)) + ok = 1; + else + { unsigned char *tmp = NULL; + ASN1_STRING_to_UTF8(&tmp, name); + if (tmp) + { if (!soap_tag_cmp(host, (const char*)tmp)) + ok = 1; + OPENSSL_free(tmp); + } + } + } + } while (!ok); + } + X509_free(peer); + if (!ok) + { soap_set_sender_error(soap, "SSL error", "SSL certificate host name mismatch in tcp_connect()", SOAP_SSL_ERROR); + soap->fclosesocket(soap, fd); + return SOAP_INVALID_SOCKET; + } + } + } +#else + soap->fclosesocket(soap, fd); + soap->error = SOAP_SSL_ERROR; + return SOAP_INVALID_SOCKET; +#endif + } + return fd; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +SOAP_FMAC1 +SOAP_SOCKET +SOAP_FMAC2 +soap_bind(struct soap *soap, const char *host, int port, int backlog) +{ +#ifdef WITH_IPV6 + struct addrinfo *addrinfo = NULL; + struct addrinfo hints; + struct addrinfo res; + int err; +#endif +#ifndef WITH_LEAN + int len = SOAP_BUFLEN; + int set = 1; +#endif + if (soap_valid_socket(soap->master)) + { soap->fclosesocket(soap, soap->master); + soap->master = SOAP_INVALID_SOCKET; + } + soap->socket = SOAP_INVALID_SOCKET; + soap->errmode = 1; + if (tcp_init(soap)) + { soap_set_receiver_error(soap, tcp_error(soap), "TCP init failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#ifdef WITH_IPV6 + memset((void*)&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; +#ifndef WITH_LEAN + if ((soap->omode & SOAP_IO_UDP)) + hints.ai_socktype = SOCK_DGRAM; + else +#endif + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + soap->errmode = 2; + err = getaddrinfo(host, soap_int2s(soap, port), &hints, &addrinfo); + if (addrinfo) + { res = *addrinfo; + memcpy(&soap->peer, addrinfo->ai_addr, addrinfo->ai_addrlen); + soap->peerlen = addrinfo->ai_addrlen; + res.ai_addr = (struct sockaddr*)&soap->peer; + res.ai_addrlen = soap->peerlen; + freeaddrinfo(addrinfo); + } + if (err || !addrinfo) + { soap_set_receiver_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + soap->master = (int)socket(res.ai_family, res.ai_socktype, res.ai_protocol); +#else +#ifndef WITH_LEAN + if ((soap->omode & SOAP_IO_UDP)) + soap->master = (int)socket(AF_INET, SOCK_DGRAM, 0); + else +#endif + soap->master = (int)socket(AF_INET, SOCK_STREAM, 0); +#endif + soap->errmode = 0; + if (!soap_valid_socket(soap->master)) + { soap->errnum = soap_socket_errno(soap->master); + soap_set_receiver_error(soap, tcp_error(soap), "socket failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#ifndef WITH_LEAN + if ((soap->omode & SOAP_IO_UDP)) + soap->socket = soap->master; +#endif +#ifdef SOCKET_CLOSE_ON_EXEC +#ifdef WIN32 +#ifndef UNDER_CE + SetHandleInformation((HANDLE)soap->master, HANDLE_FLAG_INHERIT, 0); +#endif +#else + fcntl(soap->master, F_SETFD, 1); +#endif +#endif +#ifndef WITH_LEAN + if (soap->bind_flags && setsockopt(soap->master, SOL_SOCKET, soap->bind_flags, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->master); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt(soap->master, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->master); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + if (setsockopt(soap->master, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->master); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + if (setsockopt(soap->master, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->master); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#ifdef TCP_NODELAY + if (!(soap->omode & SOAP_IO_UDP) && setsockopt(soap->master, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->master); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#endif +#endif +#ifdef WITH_IPV6 + soap->errmode = 0; + if (bind(soap->master, res.ai_addr, (int)res.ai_addrlen)) + { soap->errnum = soap_socket_errno(soap->master); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n")); + soap_closesock(soap); + soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#else + soap->peerlen = sizeof(soap->peer); + memset((void*)&soap->peer, 0, sizeof(soap->peer)); + soap->peer.sin_family = AF_INET; + soap->errmode = 2; + if (host) + { if (soap->fresolve(soap, host, &soap->peer.sin_addr)) + { soap_set_receiver_error(soap, tcp_error(soap), "get host by name failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + } + else + soap->peer.sin_addr.s_addr = htonl(INADDR_ANY); + soap->peer.sin_port = htons((short)port); + soap->errmode = 0; + if (bind(soap->master, (struct sockaddr*)&soap->peer, (int)soap->peerlen)) + { soap->errnum = soap_socket_errno(soap->master); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n")); + soap_closesock(soap); + soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#endif + if (!(soap->omode & SOAP_IO_UDP) && listen(soap->master, backlog)) + { soap->errnum = soap_socket_errno(soap->master); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n")); + soap_closesock(soap); + soap_set_receiver_error(soap, tcp_error(soap), "listen failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + return soap->master; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_poll(struct soap *soap) +{ +#ifndef WITH_LEAN + struct timeval timeout; + fd_set rfd, sfd, xfd; + register int r; +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + return SOAP_FD_EXCEEDED; /* Hint: MUST increase FD_SETSIZE */ +#endif + timeout.tv_sec = 0; + timeout.tv_usec = 0; + FD_ZERO(&rfd); + FD_ZERO(&sfd); + FD_ZERO(&xfd); + if (soap_valid_socket(soap->socket)) + { FD_SET(soap->socket, &rfd); + FD_SET(soap->socket, &sfd); + FD_SET(soap->socket, &xfd); + r = select((int)soap->socket + 1, &rfd, &sfd, &xfd, &timeout); + if (r > 0 && FD_ISSET(soap->socket, &xfd)) + r = -1; + } + else if (soap_valid_socket(soap->master)) + { FD_SET(soap->master, &sfd); + r = select((int)soap->master + 1, NULL, &sfd, NULL, &timeout); + } + else + return SOAP_OK; + if (r > 0) + { +#ifdef WITH_OPENSSL + if (soap->imode & SOAP_ENC_SSL) + { + if (soap_valid_socket(soap->socket) + && FD_ISSET(soap->socket, &sfd) + && (!FD_ISSET(soap->socket, &rfd) + || SSL_peek(soap->ssl, soap->tmpbuf, 1) > 0)) + return SOAP_OK; + } + else +#endif + if (soap_valid_socket(soap->socket) + && FD_ISSET(soap->socket, &sfd) + && (!FD_ISSET(soap->socket, &rfd) + || recv(soap->socket, soap->tmpbuf, 1, MSG_PEEK) > 0)) + return SOAP_OK; + } + else if (r < 0) + { soap->errnum = soap_socket_errno(soap->master); + if ((soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) && soap_socket_errno(soap->master) != SOAP_EINTR) + { soap_set_receiver_error(soap, tcp_error(soap), "select failed in soap_poll()", SOAP_TCP_ERROR); + return soap->error = SOAP_TCP_ERROR; + } + } + else + soap->errnum = 0; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Polling: other end down on socket=%d select=%d\n", soap->socket, r)); + return SOAP_EOF; +#else + return SOAP_OK; +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static SOAP_SOCKET +tcp_accept(struct soap *soap, SOAP_SOCKET s, struct sockaddr *a, int *n) +{ SOAP_SOCKET fd; + fd = accept(s, a, (SOAP_SOCKLEN_T*)n); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */ +#ifdef SOCKET_CLOSE_ON_EXEC +#ifdef WIN32 +#ifndef UNDER_CE + SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0); +#endif +#else + fcntl(fd, F_SETFD, FD_CLOEXEC); +#endif +#endif + return fd; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +SOAP_FMAC1 +SOAP_SOCKET +SOAP_FMAC2 +soap_accept(struct soap *soap) +{ int n = (int)sizeof(soap->peer); +#ifndef WITH_LEAN + int len = SOAP_BUFLEN; + int set = 1; +#endif + soap->error = SOAP_OK; +#ifndef WITH_LEAN + if ((soap->omode & SOAP_IO_UDP)) + return soap->socket = soap->master; +#endif + memset((void*)&soap->peer, 0, sizeof(soap->peer)); + soap->socket = SOAP_INVALID_SOCKET; + soap->errmode = 0; + soap->keep_alive = 0; + if (soap_valid_socket(soap->master)) + { register int err; + for (;;) + { +#ifndef WITH_LEAN + if (soap->accept_timeout || soap->send_timeout || soap->recv_timeout) + { +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + { soap->error = SOAP_FD_EXCEEDED; + return SOAP_INVALID_SOCKET; /* Hint: MUST increase FD_SETSIZE */ + } +#endif + for (;;) + { struct timeval timeout; + fd_set fd; + register int r; + if (soap->accept_timeout > 0) + { timeout.tv_sec = soap->accept_timeout; + timeout.tv_usec = 0; + } + else if (soap->accept_timeout < 0) + { timeout.tv_sec = -soap->accept_timeout/1000000; + timeout.tv_usec = -soap->accept_timeout%1000000; + } + else + { timeout.tv_sec = 60; + timeout.tv_usec = 0; + } + FD_ZERO(&fd); + FD_SET(soap->master, &fd); + r = select((int)soap->master + 1, &fd, &fd, &fd, &timeout); + if (r > 0) + break; + if (!r && soap->accept_timeout) + { soap->errnum = 0; + soap_set_receiver_error(soap, "Timeout", "accept failed in soap_accept()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + if (r < 0) + { r = soap_socket_errno(soap->master); + if (r != SOAP_EINTR) + { soap->errnum = r; + soap_closesock(soap); + soap_set_sender_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + } + } + } + if (soap->accept_timeout || soap->send_timeout || soap->recv_timeout) + SOAP_SOCKNONBLOCK(soap->master) + else + SOAP_SOCKBLOCK(soap->master) +#endif + soap->socket = soap->faccept(soap, soap->master, (struct sockaddr*)&soap->peer, &n); + soap->peerlen = (size_t)n; + if (soap_valid_socket(soap->socket)) + { +#ifdef WITH_IPV6 +/* Use soap->host to store the numeric form of the remote host */ + getnameinfo((struct sockaddr*)&soap->peer, n, soap->host, sizeof(soap->host), NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket %d from %s\n", soap->socket, soap->host)); + soap->ip = 0; /* info stored in soap->peer and soap->host */ + soap->port = 0; /* info stored in soap->peer and soap->host */ +#else + soap->ip = ntohl(soap->peer.sin_addr.s_addr); + soap->port = (int)ntohs(soap->peer.sin_port); /* does not return port number on some systems */ + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket %d at port %d from IP %d.%d.%d.%d\n", soap->socket, soap->port, (int)(soap->ip>>24)&0xFF, (int)(soap->ip>>16)&0xFF, (int)(soap->ip>>8)&0xFF, (int)soap->ip&0xFF)); +#endif +#ifndef WITH_LEAN + if (soap->accept_flags == SO_LINGER) + { struct linger linger; + memset((void*)&linger, 0, sizeof(linger)); + linger.l_onoff = 1; + linger.l_linger = 0; + if (setsockopt(soap->socket, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger))) + { soap->errnum = soap_socket_errno(soap->socket); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } + } + else if (soap->accept_flags && setsockopt(soap->socket, SOL_SOCKET, soap->accept_flags, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->socket); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } + if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt(soap->socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->socket); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } + if (setsockopt(soap->socket, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->socket); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } + if (setsockopt(soap->socket, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->socket); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } +#ifdef TCP_NODELAY + if (!(soap->omode & SOAP_IO_UDP) && setsockopt(soap->socket, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->socket); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } +#endif +#endif + soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0); + return soap->socket; + } + err = soap_socket_errno(soap->socket); + if (err != 0 && err != SOAP_EINTR && err != SOAP_EAGAIN && err != SOAP_EWOULDBLOCK) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept failed from %s\n", soap->host)); + soap->errnum = err; + soap_set_receiver_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } + } + } + else + { soap->errnum = 0; + soap_set_receiver_error(soap, tcp_error(soap), "no master socket in soap_accept()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_disconnect(struct soap *soap) +{ +#ifdef WITH_OPENSSL + if (soap->ssl) + { int r, s = 0; + if (soap->session) + { SSL_SESSION_free(soap->session); + soap->session = NULL; + } + if (*soap->host) + { soap->session = SSL_get1_session(soap->ssl); + if (soap->session) + { strcpy(soap->session_host, soap->host); + soap->session_port = soap->port; + } + } + r = SSL_shutdown(soap->ssl); + if (r == 0) + { if (soap_valid_socket(soap->socket)) + { struct timeval timeout; + fd_set fd; + if (soap->fshutdownsocket(soap, soap->socket, 1)) + { /* + wait up to 10 seconds for close_notify to be sent by peer (if peer not + present, this avoids calling SSL_shutdown() which has a lengthy return + timeout) + */ +#ifndef WIN32 + if ((int)soap->socket < (int)FD_SETSIZE) + { +#endif + timeout.tv_sec = 10; + timeout.tv_usec = 0; + FD_ZERO(&fd); + FD_SET(soap->socket, &fd); + r = select((int)soap->socket + 1, &fd, NULL, &fd, &timeout); + if (r <= 0 && soap_socket_errno(soap->socket) != SOAP_EINTR) + { soap->errnum = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connection lost...\n")); + soap->fclosesocket(soap, soap->socket); + soap->socket = SOAP_INVALID_SOCKET; + SSL_free(soap->ssl); + soap->ssl = NULL; + ERR_remove_state(0); + return SOAP_OK; + } +#ifndef WIN32 + } +#endif + } + } + r = SSL_shutdown(soap->ssl); + } + if (r != 1) + { s = ERR_get_error(); + if (s) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown failed: %d\n", SSL_get_error(soap->ssl, r))); + if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP)) + { soap->fclosesocket(soap, soap->socket); + soap->socket = SOAP_INVALID_SOCKET; + } + SSL_free(soap->ssl); + soap->ssl = NULL; + ERR_remove_state(0); + return SOAP_SSL_ERROR; + } + } + SSL_free(soap->ssl); + soap->ssl = NULL; + ERR_remove_state(0); + } +#endif + if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP)) + { soap->fshutdownsocket(soap, soap->socket, 2); + soap->fclosesocket(soap, soap->socket); + soap->socket = SOAP_INVALID_SOCKET; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_closesocket(struct soap *soap, SOAP_SOCKET fd) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Close socket %d\n", (int)fd)); + return soap_closesocket(fd); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_shutdownsocket(struct soap *soap, SOAP_SOCKET fd, int how) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown socket %d how=%d\n", (int)fd, how)); + return shutdown(fd, how); +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_closesock(struct soap *soap) +{ register int status = soap->error; + if (status == SOAP_EOF || status == SOAP_TCP_ERROR || status == SOAP_SSL_ERROR || !soap->keep_alive) + { if (soap->fclose && (soap->error = soap->fclose(soap))) + return soap->error; + soap->keep_alive = 0; + } +#ifdef WITH_ZLIB + if (soap->zlib_state == SOAP_ZLIB_DEFLATE) + deflateEnd(soap->d_stream); + else if (soap->zlib_state == SOAP_ZLIB_INFLATE) + inflateEnd(soap->d_stream); + soap->zlib_state = SOAP_ZLIB_NONE; +#endif + return soap->error = status; +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_hash(register const char *s) +{ register size_t h = 0; + while (*s) + h = 65599*h + *s++; + return h % SOAP_IDHASH; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static void +soap_init_pht(struct soap *soap) +{ register int i; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing pointer hashtable\n")); + soap->pblk = NULL; + soap->pidx = 0; + for (i = 0; i < (int)SOAP_PTRHASH; i++) + soap->pht[i] = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_new1(soap_mode mode) +{ return soap_new2(mode, mode); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_new() +{ return soap_new2(SOAP_IO_DEFAULT, SOAP_IO_DEFAULT); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_new2(soap_mode imode, soap_mode omode) +{ struct soap *soap = (struct soap*)malloc(sizeof(struct soap)); + if (soap) + soap_init2(soap, imode, omode); + return soap; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_free(struct soap *soap) +{ soap_done(soap); + free(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_del(struct soap *soap) +{ free(soap); +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static void +soap_free_pht(struct soap *soap) +{ register struct soap_pblk *pb, *next; + register int i; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free pointer hashtable\n")); + for (pb = soap->pblk; pb; pb = next) + { next = pb->next; + SOAP_FREE(soap, pb); + } + soap->pblk = NULL; + soap->pidx = 0; + for (i = 0; i < (int)SOAP_PTRHASH; i++) + soap->pht[i] = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_embed(struct soap *soap, const void *p, const struct soap_array *a, int n, const char *tag, int type) +{ register int i; + struct soap_plist *pp; + if (soap->version != 1) + soap->encoding = 1; + if (a) + i = soap_array_pointer_lookup(soap, p, a, n, type, &pp); + else + i = soap_pointer_lookup(soap, p, type, &pp); + if (i) + { if (soap_is_embedded(soap, pp) + || soap_is_single(soap, pp)) + return 0; + soap_set_embedded(soap, pp); + } + return i; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_pointer_lookup(struct soap *soap, const void *p, int type, struct soap_plist **ppp) +{ register struct soap_plist *pp; + *ppp = NULL; + if (p) + { for (pp = soap->pht[soap_hash_ptr(p)]; pp; pp = pp->next) + { if (pp->ptr == p && pp->type == type) + { *ppp = pp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d id=%d\n", p, type, pp->id)); + return pp->id; + } + } + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d: not found\n", p, type)); + return 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_pointer_enter(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp) +{ register size_t h; + register struct soap_plist *pp; + if (!soap->pblk || soap->pidx >= SOAP_PTRBLK) + { register struct soap_pblk *pb = (struct soap_pblk*)SOAP_MALLOC(soap, sizeof(struct soap_pblk)); + if (!pb) + { soap->error = SOAP_EOM; + return 0; + } + pb->next = soap->pblk; + soap->pblk = pb; + soap->pidx = 0; + } + *ppp = pp = &soap->pblk->plist[soap->pidx++]; + if (a) + h = soap_hash_ptr(a->__ptr); + else + h = soap_hash_ptr(p); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pointer enter location=%p array=%p size=%d dim=%d type=%d id=%d\n", p, a?a->__ptr:NULL, a?a->__size:0, n, type, soap->idnum+1)); + pp->next = soap->pht[h]; + pp->type = type; + pp->mark1 = 0; + pp->mark2 = 0; + pp->ptr = p; + pp->array = a; + soap->pht[h] = pp; + pp->id = ++soap->idnum; + return pp->id; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_array_pointer_lookup(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp) +{ register struct soap_plist *pp; + *ppp = NULL; + if (!p || !a->__ptr) + return 0; + for (pp = soap->pht[soap_hash_ptr(a->__ptr)]; pp; pp = pp->next) + { if (pp->type == type && pp->array && pp->array->__ptr == a->__ptr) + { register int i; + for (i = 0; i < n; i++) + if (((const int*)&pp->array->__size)[i] != ((const int*)&a->__size)[i]) + break; + if (i == n) + { *ppp = pp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d id=%d\n", a->__ptr, type, pp->id)); + return pp->id; + } + } + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d: not found\n", a->__ptr, type)); + return 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_begin_count(struct soap *soap) +{ +#ifndef WITH_LEANER + if ((soap->mode & SOAP_ENC_DIME) || (soap->omode & SOAP_ENC_DIME)) + soap->mode = soap->omode | SOAP_IO_LENGTH | SOAP_ENC_DIME; + else +#endif + { soap->mode = soap->omode; + if ((soap->mode & SOAP_IO) == SOAP_IO_STORE + || (((soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_ENC_XML)) +#ifndef WITH_LEANER + && !soap->fpreparesend +#endif + )) + soap->mode &= ~SOAP_IO_LENGTH; + else + soap->mode |= SOAP_IO_LENGTH; + } +#ifdef WITH_ZLIB + if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH) + { if (!(soap->mode & SOAP_ENC_DIME)) + soap->mode &= ~SOAP_IO_LENGTH; + if (soap->mode & SOAP_ENC_XML) + soap->mode |= SOAP_IO_BUFFER; + else + soap->mode |= SOAP_IO_STORE; + } +#endif + if (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH)) + soap->mode |= SOAP_XML_TREE; +#ifndef WITH_LEANER + if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME)) + soap->mode |= SOAP_ENC_MIME; + else + soap->mode &= ~SOAP_ENC_MTOM; + if (soap->mode & SOAP_ENC_MIME) + soap_select_mime_boundary(soap); + soap->dime.list = soap->dime.last; /* keep track of last DIME attachment */ +#endif + soap->count = 0; + soap->ns = 0; + soap->null = 0; + soap->position = 0; + soap->mustUnderstand = 0; + soap->encoding = 0; + soap->part = SOAP_BEGIN; + soap->idnum = 0; + soap_clr_attr(soap); + soap_set_local_namespaces(soap); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin count phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count)); +#ifndef WITH_LEANER + soap->dime.count = 0; /* count # of attachments */ + soap->dime.size = 0; /* accumulate total size of attachments */ + if (soap->fprepareinit && (soap->mode & SOAP_IO) != SOAP_IO_STORE) + return soap->error = soap->fprepareinit(soap); +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_end_count(struct soap *soap) +{ +#ifndef WITH_LEANER + if (soap->fpreparefinal) + return soap->error = soap->fpreparefinal(soap); +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of count phase\n")); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_begin_send(struct soap *soap) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing for output\n")); + soap->error = SOAP_OK; + soap->mode = soap->omode | (soap->mode & (SOAP_IO_LENGTH | SOAP_ENC_DIME)); +#ifdef WITH_ZLIB + if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH) + { if (soap->mode & SOAP_ENC_XML) + soap->mode |= SOAP_IO_BUFFER; + else + soap->mode |= SOAP_IO_STORE; + } +#endif +#ifndef WITH_LEAN + if ((soap->mode & SOAP_IO_UDP)) + { soap->mode |= SOAP_ENC_XML; + if (soap->count > SOAP_BUFLEN) + return soap->error = SOAP_UDP_ERROR; + } +#endif + if ((soap->mode & SOAP_IO) == SOAP_IO_FLUSH && soap_valid_socket(soap->socket)) + { if (soap->count || (soap->mode & SOAP_IO_LENGTH) || (soap->mode & SOAP_ENC_XML)) + soap->mode |= SOAP_IO_BUFFER; + else + soap->mode |= SOAP_IO_STORE; + } + soap->mode &= ~SOAP_IO_LENGTH; + if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) + soap_new_block(soap); + if (!(soap->mode & SOAP_IO_KEEPALIVE)) + soap->keep_alive = 0; + if (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH)) + soap->mode |= SOAP_XML_TREE; +#ifndef WITH_LEANER + if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME)) + { soap->mode |= SOAP_ENC_MIME; + soap->mode &= ~SOAP_ENC_DIME; + } + else + soap->mode &= ~SOAP_ENC_MTOM; + if (soap->mode & SOAP_ENC_MIME) + soap_select_mime_boundary(soap); +#ifdef WIN32 +#ifndef UNDER_CE +#ifndef WITH_FASTCGI + if (!soap_valid_socket(soap->socket)) /* Set win32 stdout or soap->sendfd to BINARY, e.g. to support DIME */ +#ifdef __BORLANDC__ + setmode(soap->sendfd, O_BINARY); +#else + _setmode(soap->sendfd, _O_BINARY); +#endif +#endif +#endif +#endif +#endif + if (soap->mode & SOAP_IO) + { soap->bufidx = 0; + soap->buflen = 0; + } + soap->chunksize = 0; + soap->ns = 0; + soap->null = 0; + soap->position = 0; + soap->mustUnderstand = 0; + soap->encoding = 0; + soap->idnum = 0; + soap->level = 0; + soap_clr_attr(soap); + soap_set_local_namespaces(soap); +#ifdef WITH_ZLIB + soap->z_ratio_out = 1.0; + if ((soap->mode & SOAP_ENC_ZLIB) && soap->zlib_state != SOAP_ZLIB_DEFLATE) + { if (!soap->z_buf) + soap->z_buf = (char*)SOAP_MALLOC(soap, SOAP_BUFLEN); + soap->d_stream->next_out = (Byte*)soap->z_buf; + soap->d_stream->avail_out = SOAP_BUFLEN; +#ifdef WITH_GZIP + if (soap->zlib_out != SOAP_ZLIB_DEFLATE) + { memcpy(soap->z_buf, "\37\213\10\0\0\0\0\0\0\377", 10); + soap->d_stream->next_out = (Byte*)soap->z_buf + 10; + soap->d_stream->avail_out = SOAP_BUFLEN - 10; + soap->z_crc = crc32(0L, NULL, 0); + soap->zlib_out = SOAP_ZLIB_GZIP; + if (deflateInit2(soap->d_stream, soap->z_level, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; + } + else +#endif + if (deflateInit(soap->d_stream, soap->z_level) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflate initialized\n")); + soap->zlib_state = SOAP_ZLIB_DEFLATE; + } +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin send phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count)); + soap->part = SOAP_BEGIN; +#ifndef WITH_LEANER + if (soap->fprepareinit && (soap->mode & SOAP_IO) == SOAP_IO_STORE) + soap->fprepareinit(soap); +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_embedded(struct soap *soap, const void *p, int t) +{ struct soap_plist *pp; + if (soap_pointer_lookup(soap, p, t, &pp)) + { pp->mark1 = 1; + pp->mark2 = 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded %p type=%d mark set to 1\n", p, t)); + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_reference(struct soap *soap, const void *p, int t) +{ struct soap_plist *pp; + if (!p || (soap->mode & SOAP_XML_TREE)) + return 1; + if (soap_pointer_lookup(soap, p, t, &pp)) + { if (pp->mark1 == 0) + { pp->mark1 = 2; + pp->mark2 = 2; + } + } + else if (soap_pointer_enter(soap, p, NULL, 0, t, &pp)) + { pp->mark1 = 0; + pp->mark2 = 0; + } + else + return 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reference %p type=%d (%d %d)\n", p, t, (int)pp->mark1, (int)pp->mark2)); + return pp->mark1; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_array_reference(struct soap *soap, const void *p, const struct soap_array *a, int n, int t) +{ register int i; + struct soap_plist *pp; + if (!p || !a->__ptr) + return 1; + i = soap_array_pointer_lookup(soap, p, a, n, t, &pp); + if (i) + { if (pp->mark1 == 0) + { pp->mark1 = 2; + pp->mark2 = 2; + } + } + else if (!soap_pointer_enter(soap, p, a, n, t, &pp)) + return 1; + else + { pp->mark1 = 0; + pp->mark2 = 0; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array reference %p ptr=%p dim=%d type=%d (%d %d)\n", p, a->__ptr, n, t, (int)pp->mark1, (int)pp->mark2)); + return pp->mark1; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_embedded_id(struct soap *soap, int id, const void *p, int t) +{ struct soap_plist *pp = NULL; + if (soap->mode & SOAP_XML_TREE) + return id; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id %p type=%d id=%d\n", p, t, id)); + if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER) + { if (id < 0) + { id = soap_pointer_lookup(soap, p, t, &pp); + if (id) + { if (soap->mode & SOAP_IO_LENGTH) + pp->mark1 = 2; + else + pp->mark2 = 2; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id multiref id=%d %p type=%d = (%d %d)\n", id, p, t, (int)pp->mark1, (int)pp->mark2)); + } + return -1; + } + return id; + } + if (id < 0) + id = soap_pointer_lookup(soap, p, t, &pp); + else if (id && !soap_pointer_lookup(soap, p, t, &pp)) + return 0; + if (id && pp) + { if (soap->mode & SOAP_IO_LENGTH) + pp->mark1 = 1; + else + pp->mark2 = 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id embedded ref id=%d %p type=%d = (%d %d)\n", id, p, t, (int)pp->mark1, (int)pp->mark2)); + } + return id; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_is_embedded(struct soap *soap, struct soap_plist *pp) +{ if (!pp) + return 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Is embedded? %d %d\n", (int)pp->mark1, (int)pp->mark2)); + if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER) + { if (soap->mode & SOAP_IO_LENGTH) + return pp->mark1 != 0; + return pp->mark2 != 0; + } + if (soap->mode & SOAP_IO_LENGTH) + return pp->mark1 == 1; + return pp->mark2 == 1; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_is_single(struct soap *soap, struct soap_plist *pp) +{ if (soap->part == SOAP_IN_HEADER) + return 1; + if (!pp) + return 0; + if (soap->mode & SOAP_IO_LENGTH) + return pp->mark1 == 0; + return pp->mark2 == 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_embedded(struct soap *soap, struct soap_plist *pp) +{ if (!pp) + return; + if (soap->mode & SOAP_IO_LENGTH) + pp->mark1 = 1; + else + pp->mark2 = 1; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_attachment(struct soap *soap, const char *tag, int id, const void *p, const struct soap_array *a, const char *aid, const char *atype, const char *aoptions, int n, const char *type, int t) +{ +#ifndef WITH_NOIDREF + struct soap_plist *pp; + int i; + if (!p || !a->__ptr || (!aid && !atype)) + return soap_element_id(soap, tag, id, p, a, n, type, t); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attachment tag='%s' id='%s' (%d) type='%s'\n", tag, aid?aid:"", id, atype?atype:"")); + i = soap_array_pointer_lookup(soap, p, a, n, t, &pp); + if (!i) + { i = soap_pointer_enter(soap, p, a, n, t, &pp); + if (!i) + { soap->error = SOAP_EOM; + return -1; + } + } + if (id <= 0) + id = i; + if (!aid) + { sprintf(soap->tmpbuf, soap->dime_id_format, id); + aid = soap_strdup(soap, soap->tmpbuf); + } + /* Add MTOM xop:Include element when necessary */ + /* TODO: this code to be obsoleted with new import/xop.h conventions */ + if ((soap->mode & SOAP_ENC_MTOM) && strcmp(tag, "xop:Include")) + { if (soap_element_begin_out(soap, tag, 0, type) + || soap_element_href(soap, "xop:Include", 0, "href", aid) + || soap_element_end_out(soap, tag)) + return soap->error; + } + else if (soap_element_href(soap, tag, 0, "href", aid)) + return soap->error; + if (soap->mode & SOAP_IO_LENGTH) + { if (pp->mark1 != 3) + { struct soap_multipart *content; + if (soap->mode & SOAP_ENC_MTOM) + content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, (char*)a->__ptr, a->__size); + else + content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, (char*)a->__ptr, a->__size); + if (!content) + { soap->error = SOAP_EOM; + return -1; + } + if (!strncmp(aid, "cid:", 4)) /* RFC 2111 */ + { if (soap->mode & SOAP_ENC_MTOM) + { char *s = (char*)soap_malloc(soap, strlen(aid) - 1); + if (s) + { *s = '<'; + strcpy(s + 1, aid + 4); + strcat(s, ">"); + content->id = s; + } + } + else + content->id = aid + 4; + } + else + content->id = aid; + content->type = atype; + content->options = aoptions; + content->encoding = SOAP_MIME_BINARY; + pp->mark1 = 3; + } + } + else + pp->mark2 = 3; +#endif + return -1; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static void +soap_init_iht(struct soap *soap) +{ register int i; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing ID hashtable\n")); + for (i = 0; i < SOAP_IDHASH; i++) + soap->iht[i] = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static void +soap_free_iht(struct soap *soap) +{ register int i; + register struct soap_ilist *ip = NULL, *p = NULL; + register struct soap_flist *fp = NULL, *fq = NULL; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free ID hashtable\n")); + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = p) + { for (fp = ip->flist; fp; fp = fq) + { fq = fp->next; + SOAP_FREE(soap, fp); + } + p = ip->next; + SOAP_FREE(soap, ip); + } + soap->iht[i] = NULL; + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +struct soap_ilist * +SOAP_FMAC2 +soap_lookup(struct soap *soap, const char *id) +{ register struct soap_ilist *ip = NULL; + for (ip = soap->iht[soap_hash(id)]; ip; ip = ip->next) + if (!strcmp(ip->id, id)) + return ip; + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +struct soap_ilist * +SOAP_FMAC2 +soap_enter(struct soap *soap, const char *id) +{ register size_t h; + register struct soap_ilist *ip; + ip = (struct soap_ilist*)SOAP_MALLOC(soap, sizeof(struct soap_ilist) + strlen(id)); + if (ip) + { h = soap_hash(id); + strcpy(ip->id, id); + ip->next = soap->iht[h]; + soap->iht[h] = ip; + return ip; + } + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_malloc(struct soap *soap, size_t n) +{ register char *p; + if (!n) + return (void*)SOAP_NON_NULL; + if (!soap) + return SOAP_MALLOC(soap, n); + if (soap->fmalloc) + p = (char*)soap->fmalloc(soap, n); + else + { n += sizeof(short); + n += (-(long)n) & (sizeof(void*)-1); /* align at 4-, 8- or 16-byte boundary */ + if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(void*) + sizeof(size_t)))) + { soap->error = SOAP_EOM; + return NULL; + } + /* set the canary to detect corruption */ + *(short*)(p + n - sizeof(short)) = (short)SOAP_CANARY; + /* keep chain of alloced cells for destruction */ + *(void**)(p + n) = soap->alist; + *(size_t*)(p + n + sizeof(void*)) = n; + soap->alist = p + n; + } + soap->alloced = 1; + return p; +} +#endif + +/******************************************************************************/ +#ifdef SOAP_MEM_DEBUG +static void +soap_init_mht(struct soap *soap) +{ register int i; + for (i = 0; i < (int)SOAP_PTRHASH; i++) + soap->mht[i] = NULL; +} +#endif + +/******************************************************************************/ +#ifdef SOAP_MEM_DEBUG +static void +soap_free_mht(struct soap *soap) +{ register int i; + register struct soap_mlist *mp, *mq; + for (i = 0; i < (int)SOAP_PTRHASH; i++) + { for (mp = soap->mht[i]; mp; mp = mq) + { mq = mp->next; + if (mp->live) + fprintf(stderr, "%s(%d): malloc() = %p not freed (memory leak or forgot to call soap_end()?)\n", mp->file, mp->line, mp->ptr); + free(mp); + } + soap->mht[i] = NULL; + } +} +#endif + +/******************************************************************************/ +#ifdef SOAP_MEM_DEBUG +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_track_malloc(struct soap *soap, const char *file, int line, size_t size) +{ register void *p = malloc(size); + if (soap) + { register size_t h = soap_hash_ptr(p); + register struct soap_mlist *mp = (struct soap_mlist*)malloc(sizeof(struct soap_mlist)); + if (soap->fdebug[SOAP_INDEX_TEST]) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): malloc(%lu) = %p\n", file, line, (unsigned long)size, p)); + } + mp->next = soap->mht[h]; + mp->ptr = p; + mp->file = file; + mp->line = line; + mp->live = 1; + soap->mht[h] = mp; + } + return p; +} +#endif + +/******************************************************************************/ +#ifdef SOAP_MEM_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_track_free(struct soap *soap, const char *file, int line, void *p) +{ register size_t h = soap_hash_ptr(p); + register struct soap_mlist *mp; + for (mp = soap->mht[h]; mp; mp = mp->next) + if (mp->ptr == p) + break; + if (mp) + { if (mp->live) + { free(p); + if (soap->fdebug[SOAP_INDEX_TEST]) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): free(%p)\n", file, line, p)); + } + mp->live = 0; + } + else + fprintf(stderr, "%s(%d): free(%p) double free of pointer malloced at %s(%d)\n", file, line, p, mp->file, mp->line); + } + else + fprintf(stderr, "%s(%d): free(%p) pointer not malloced\n", file, line, p); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_MEM_DEBUG +static void +soap_track_unlink(struct soap *soap, const void *p) +{ register size_t h = soap_hash_ptr(p); + register struct soap_mlist *mp; + for (mp = soap->mht[h]; mp; mp = mp->next) + if (mp->ptr == p) + break; + if (mp) + mp->live = 0; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_dealloc(struct soap *soap, void *p) +{ if (soap_check_state(soap)) + return; + if (p) + { register char **q; + for (q = (char**)&soap->alist; *q; q = *(char***)q) + { + if (*(short*)(char*)(*q - sizeof(short)) != (short)SOAP_CANARY) + { +#ifdef SOAP_MEM_DEBUG + fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n"); +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n")); + DBGHEX(TEST, *q - 200, 200); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n")); + soap->error = SOAP_MOE; + return; + } + if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*)))) + { *q = **(char***)q; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Freed data at %p\n", p)); + SOAP_FREE(soap, p); + return; + } + } + soap_delete(soap, p); + } + else + { register char *q; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free all soap_malloc() data\n")); + while (soap->alist) + { q = (char*)soap->alist; + if (*(short*)(char*)(q - sizeof(short)) != (short)SOAP_CANARY) + { +#ifdef SOAP_MEM_DEBUG + fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n"); +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n")); + DBGHEX(TEST, q - 200, 200); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n")); + soap->error = SOAP_MOE; + return; + } + soap->alist = *(void**)q; + q -= *(size_t*)(q + sizeof(void*)); + SOAP_FREE(soap, q); + } + /* we must assume these were deallocated: */ + soap->action = NULL; + soap->fault = NULL; + soap->header = NULL; + soap->userid = NULL; + soap->passwd = NULL; + soap->authrealm = NULL; + soap->http_content = NULL; +#ifndef WITH_LEANER + soap_clr_mime(soap); +#endif + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_delete(struct soap *soap, void *p) +{ register struct soap_clist **cp; + if (soap_check_state(soap)) + return; + cp = &soap->clist; + if (p) + { while (*cp) + { if (p == (*cp)->ptr) + { register struct soap_clist *q = *cp; + *cp = q->next; + if (q->fdelete(q)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: deletion callback failed for object type %d\n", q->ptr, q->type)); +#ifdef SOAP_MEM_DEBUG + fprintf(stderr, "new(object type = %d) = %p not freed: deletion callback failed\n", q->type, q->ptr); +#endif + } + SOAP_FREE(soap, q); + return; + } + cp = &(*cp)->next; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: address not in list\n", p)); + } + else + { while (*cp) + { register struct soap_clist *q = *cp; + *cp = q->next; + if (q->fdelete(q)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: deletion callback failed for object type %d\n", q->ptr, q->type)); +#ifdef SOAP_MEM_DEBUG + fprintf(stderr, "new(object type = %d) = %p not freed: deletion callback failed\n", q->type, q->ptr); +#endif + } + SOAP_FREE(soap, q); + } + } + soap->fault = NULL; /* this was possibly deallocated */ + soap->header = NULL; /* this was possibly deallocated */ +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +struct soap_clist * +SOAP_FMAC2 +soap_link(struct soap *soap, void *p, int t, int n, int (*fdelete)(struct soap_clist*)) +{ register struct soap_clist *cp; + if ((cp = (struct soap_clist*)SOAP_MALLOC(soap, sizeof(struct soap_clist)))) + { cp->next = soap->clist; + cp->type = t; + cp->size = n; + cp->ptr = p; + cp->fdelete = fdelete; + soap->clist = cp; + } + return cp; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_unlink(struct soap *soap, const void *p) +{ register char **q; + register struct soap_clist **cp; + if (!soap || !p) + return; + for (q = (char**)&soap->alist; *q; q = *(char***)q) + { if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*)))) + { *q = **(char***)q; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked data %p\n", p)); +#ifdef SOAP_MEM_DEBUG + soap_track_unlink(soap, p); +#endif + return; + } + } + for (cp = &soap->clist; *cp; cp = &(*cp)->next) + { if (p == (*cp)->ptr) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked class instance %p\n", p)); + q = (char**)*cp; + *cp = (*cp)->next; + SOAP_FREE(soap, q); + return; + } + } +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_lookup_type(struct soap *soap, const char *id) +{ register struct soap_ilist *ip; + if (id && *id) + { ip = soap_lookup(soap, id); + if (ip) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup id='%s' type=%d\n", id, ip->type)); + return ip->type; + } + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "lookup type id='%s' NOT FOUND! Need to get it from xsi:type\n", id)); + return 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_id_lookup(struct soap *soap, const char *id, void **p, int t, size_t n, unsigned int k) +{ struct soap_ilist *ip; + void **q; + if (!p || !id || !*id) + return p; + ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */ + if (!ip) + { ip = soap_enter(soap, id); /* new hash table entry for string id */ + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding first href='%s' type=%d %p (%u bytes)\n", id, t, p, (unsigned int)n)); + ip->type = t; + ip->size = n; + ip->link = p; + ip->copy = NULL; + ip->flist = NULL; + ip->ptr = NULL; + ip->level = k; + *p = NULL; + } + else if (ip->ptr) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolved href='%s' type=%d location=%p (%u bytes)\n", id, t, ip->ptr, (unsigned int)n)); + if (ip->type != t) + { strcpy(soap->id, id); + soap->error = SOAP_HREF; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility: href='%s' id-type=%d href-type=%d\n", id, ip->type, t)); + return NULL; + } + while (ip->level < k) + { q = (void**)soap_malloc(soap, sizeof(void*)); + if (!q) + return NULL; + *p = (void*)q; + p = q; + k--; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); + } + *p = ip->ptr; + } + else if (ip->level > k) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving level %u pointers to href='%s'\n", ip->level, id)); + while (ip->level > k) + { void *s, **r = &ip->link; + q = (void**)ip->link; + while (q) + { *r = (void*)soap_malloc(soap, sizeof(void*)); + s = *q; + *q = *r; + r = (void**)*r; + q = (void**)s; + } + *r = NULL; + ip->size = n; + ip->copy = NULL; + ip->level = ip->level - 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); + } + q = (void**)ip->link; + ip->link = p; + *p = (void*)q; + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarded href='%s' type=%d location=%p (%u bytes)\n", id, t, p, (unsigned int)n)); + while (ip->level < k) + { q = (void**)soap_malloc(soap, sizeof(void*)); + *p = q; + p = q; + k--; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); + } + q = (void**)ip->link; + ip->link = p; + *p = (void*)q; + } + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_id_forward(struct soap *soap, const char *href, void *p, size_t len, int st, int tt, size_t n, unsigned int k, void (*fcopy)(struct soap*, int, int, void*, size_t, const void*, size_t)) +{ struct soap_ilist *ip; + if (!p || !href || !*href) + return p; + ip = soap_lookup(soap, href); /* lookup pointer to hash table entry for string id */ + if (!ip) + { ip = soap_enter(soap, href); /* new hash table entry for string id */ + ip->type = st; + ip->size = n; + ip->link = NULL; + ip->copy = NULL; + ip->ptr = NULL; + ip->level = 0; + ip->flist = NULL; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "New entry href='%s' type=%d size=%lu level=%d location=%p\n", href, st, (unsigned long)n, k, p)); + } + else if (ip->type != st || (ip->level == k && ip->size != n)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n", href, ip->type, (unsigned long)ip->size, k, st, (unsigned long)n)); + strcpy(soap->id, href); + soap->error = SOAP_HREF; + return NULL; + } + if (fcopy || n < sizeof(void*) || *href != '#') + { register struct soap_flist *fp = (struct soap_flist*)SOAP_MALLOC(soap, sizeof(struct soap_flist)); + if (!fp) + { soap->error = SOAP_EOM; + return NULL; + } + fp->next = ip->flist; + fp->type = tt; + fp->ptr = p; + fp->level = k; + fp->len = len; + if (fcopy) + fp->fcopy = fcopy; + else + fp->fcopy = soap_fcopy; + ip->flist = fp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding type=%d (target type=%d) size=%lu location=%p level=%u len=%lu href='%s'\n", st, tt, (unsigned long)n, p, k, (unsigned long)len, href)); + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding copying address %p for type=%d href='%s'\n", p, st, href)); + *(void**)p = ip->copy; + ip->copy = p; + } + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_id_enter(struct soap *soap, const char *id, void *p, int t, size_t n, unsigned int k, const char *type, const char *arrayType, void *(*finstantiate)(struct soap*, int, const char*, const char*, size_t*)) +{ +#ifndef WITH_NOIDREF + struct soap_ilist *ip; +#endif + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Enter id='%s' type=%d loc=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k)); + soap->alloced = 0; + if (!p) + { if (finstantiate) + p = finstantiate(soap, t, type, arrayType, &n); + else + p = soap_malloc(soap, n); + if (p) + soap->alloced = 1; + } +#ifndef WITH_NOIDREF + if (!id || !*id) +#endif + return p; +#ifndef WITH_NOIDREF + ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */ + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Lookup entry id='%s for location=%p'\n", id, p)); + if (!ip) + { ip = soap_enter(soap, id); /* new hash table entry for string id */ + ip->type = t; + ip->link = NULL; + ip->copy = NULL; + ip->flist = NULL; + ip->size = n; + ip->ptr = p; + ip->level = k; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "New entry id='%s' type=%d size=%lu level=%u location=%p\n", id, t, (unsigned long)n, k, p)); + } + else if ((ip->type != t || (ip->level == k && ip->size != n)) && (ip->copy || ip->flist)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n", id, ip->type, (unsigned long)ip->size, k, t, (unsigned long)n)); + strcpy(soap->id, id); + soap->error = SOAP_HREF; + return NULL; + } + else if (ip->ptr) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Multiply defined id='%s'\n", id)); + strcpy(soap->id, id); + soap->error = SOAP_DUPLICATE_ID; + return NULL; + } + else + { ip->size = n; + ip->ptr = p; + ip->level = k; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update entry id='%s' type=%d location=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k)); + } + return ip->ptr; +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_fcopy(struct soap *soap, int st, int tt, void *p, size_t len, const void *q, size_t n) +{ DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Copying data type=%d (target type=%d) %p -> %p (%lu bytes)\n", st, tt, q, p, (unsigned long)n)); + memcpy(p, q, n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_end_send(struct soap *soap) +{ +#ifndef WITH_LEANER + if (soap->dime.list) + { /* SOAP body referenced attachments must appear first */ + soap->dime.last->next = soap->dime.first; + soap->dime.first = soap->dime.list->next; + soap->dime.list->next = NULL; + soap->dime.last = soap->dime.list; + } + if (soap_putdime(soap) || soap_putmime(soap)) + return soap->error; + soap->mime.list = NULL; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->dime.list = NULL; + soap->dime.first = NULL; + soap->dime.last = NULL; +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End send\n")); + if (soap->mode & SOAP_IO) /* need to flush the remaining data in buffer */ + { if (soap_flush(soap)) +#ifdef WITH_ZLIB + { if (soap->mode & SOAP_ENC_ZLIB && soap->zlib_state == SOAP_ZLIB_DEFLATE) + { soap->zlib_state = SOAP_ZLIB_NONE; + deflateEnd(soap->d_stream); + } + return soap->error; + } +#else + return soap->error; +#endif +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { int r; + soap->d_stream->avail_in = 0; + do + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating remainder\n")); + r = deflate(soap->d_stream, Z_FINISH); + if (soap->d_stream->avail_out != SOAP_BUFLEN) + { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN - soap->d_stream->avail_out)) + { soap->zlib_state = SOAP_ZLIB_NONE; + deflateEnd(soap->d_stream); + return soap->error; + } + soap->d_stream->next_out = (Byte*)soap->z_buf; + soap->d_stream->avail_out = SOAP_BUFLEN; + } + } while (r == Z_OK); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflated total %lu->%lu bytes\n", soap->d_stream->total_in, soap->d_stream->total_out)); + soap->z_ratio_out = (float)soap->d_stream->total_out / (float)soap->d_stream->total_in; + soap->mode &= ~SOAP_ENC_ZLIB; + soap->zlib_state = SOAP_ZLIB_NONE; + if (deflateEnd(soap->d_stream) != Z_OK || r != Z_STREAM_END) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to end deflate: %s\n", soap->d_stream->msg?soap->d_stream->msg:"")); + return soap->error = SOAP_ZLIB_ERROR; + } +#ifdef WITH_GZIP + if (soap->zlib_out != SOAP_ZLIB_DEFLATE) + { soap->z_buf[0] = soap->z_crc & 0xFF; + soap->z_buf[1] = (soap->z_crc >> 8) & 0xFF; + soap->z_buf[2] = (soap->z_crc >> 16) & 0xFF; + soap->z_buf[3] = (soap->z_crc >> 24) & 0xFF; + soap->z_buf[4] = soap->d_stream->total_in & 0xFF; + soap->z_buf[5] = (soap->d_stream->total_in >> 8) & 0xFF; + soap->z_buf[6] = (soap->d_stream->total_in >> 16) & 0xFF; + soap->z_buf[7] = (soap->d_stream->total_in >> 24) & 0xFF; + if (soap_flush_raw(soap, soap->z_buf, 8)) + return soap->error; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip crc32=%lu\n", (unsigned long)soap->z_crc)); + } +#endif + } +#endif + if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) + { char *p; +#ifndef WITH_NOHTTP + if (!(soap->mode & SOAP_ENC_XML)) + { soap->mode--; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending buffered message of length %u\n", (unsigned int)soap->blist->size)); + if (soap->status >= SOAP_POST) + soap->error = soap->fpost(soap, soap->endpoint, soap->host, soap->port, soap->path, soap->action, soap->blist->size); + else if (soap->status != SOAP_STOP) + soap->error = soap->fresponse(soap, soap->status, soap->blist->size); + if (soap->error || soap_flush(soap)) + return soap->error; + soap->mode++; + } +#endif + for (p = soap_first_block(soap); p; p = soap_next_block(soap)) + { DBGMSG(SENT, p, soap_block_size(soap)); + if ((soap->error = soap->fsend(soap, p, soap_block_size(soap)))) + { soap_end_block(soap); + return soap->error; + } + } + soap_end_block(soap); + } +#ifndef WITH_LEANER + else if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) + { DBGMSG(SENT, "\r\n0\r\n\r\n", 7); + if ((soap->error = soap->fsend(soap, "\r\n0\r\n\r\n", 7))) + return soap->error; + } +#endif + } +#ifdef WITH_TCPFIN +#ifdef WITH_OPENSSL + if (!soap->ssl && soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP)) + soap->fshutdownsocket(soap, soap->socket, 1); /* Send TCP FIN */ +#else + if (soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP)) + soap->fshutdownsocket(soap, soap->socket, 1); /* Send TCP FIN */ +#endif +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of send phase\n")); + soap->omode &= ~SOAP_XML_SEC; + soap->count = 0; + soap->part = SOAP_END; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_end_recv(struct soap *soap) +{ soap->part = SOAP_END; +#ifndef WITH_LEANER + if ((soap->mode & SOAP_ENC_DIME) && soap_getdime(soap)) + { soap->dime.first = NULL; + soap->dime.last = NULL; + return soap->error; + } + soap->dime.list = soap->dime.first; + soap->dime.first = NULL; + soap->dime.last = NULL; + /* Check if MIME attachments and mime-post-check flag is set, if set call soap_resolve() and return */ + if (soap->mode & SOAP_ENC_MIME) + { +#ifndef WITH_NOIDREF + if (soap->mode & SOAP_MIME_POSTCHECK) + { soap_resolve(soap); + return SOAP_OK; + } +#endif + if (soap_getmime(soap)) + return soap->error; + } + soap->mime.list = soap->mime.first; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = NULL; + if (soap->xlist) + { struct soap_multipart *content; + for (content = soap->mime.list; content; content = content->next) + soap_resolve_attachment(soap, content); + } +#endif + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "End of receive message ok\n")); +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { /* Make sure end of compressed content is reached */ + while (soap->d_stream->next_out != Z_NULL) + if ((int)soap_get1(soap) == EOF) + break; + soap->mode &= ~SOAP_ENC_ZLIB; + memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN); + soap->bufidx = (char*)soap->d_stream->next_in - soap->z_buf; + soap->buflen = soap->z_buflen; + soap->zlib_state = SOAP_ZLIB_NONE; + if (inflateEnd(soap->d_stream) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Inflate end ok\n")); +#ifdef WITH_GZIP + if (soap->zlib_in == SOAP_ZLIB_GZIP) + { soap_wchar c; + short i; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Inflate gzip crc check\n")); + for (i = 0; i < 8; i++) + { if ((int)(c = soap_get1(soap)) == EOF) + return soap->error = SOAP_EOF; + soap->z_buf[i] = (char)c; + } + if (soap->z_crc != ((uLong)(unsigned char)soap->z_buf[0] | ((uLong)(unsigned char)soap->z_buf[1] << 8) | ((uLong)(unsigned char)soap->z_buf[2] << 16) | ((uLong)(unsigned char)soap->z_buf[3] << 24))) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: crc check failed, message corrupted? (crc32=%lu)\n", (unsigned long)soap->z_crc)); + return soap->error = SOAP_ZLIB_ERROR; + } + if (soap->d_stream->total_out != ((uLong)(unsigned char)soap->z_buf[4] | ((uLong)(unsigned char)soap->z_buf[5] << 8) | ((uLong)(unsigned char)soap->z_buf[6] << 16) | ((uLong)(unsigned char)soap->z_buf[7] << 24))) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: incorrect message length\n")); + return soap->error = SOAP_ZLIB_ERROR; + } + } + soap->zlib_in = SOAP_ZLIB_NONE; +#endif + } +#endif + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) + while ((int)soap_getchar(soap) != EOF) /* advance to last chunk */ + ; + if (soap->fdisconnect && (soap->error = soap->fdisconnect(soap))) + return soap->error; +#ifndef WITH_NOIDREF + if (soap_resolve(soap)) + return soap->error; +#endif +#ifndef WITH_LEANER + if (soap->xlist) + { if (soap->mode & SOAP_ENC_MTOM) + return soap->error = SOAP_MIME_HREF; + return soap->error = SOAP_DIME_HREF; + } +#endif + soap_free_temp(soap); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_free_temp(struct soap *soap) +{ register struct soap_nlist *np, *nq; + register struct soap_attribute *tp, *tq; + register struct Namespace *ns; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free namespace stack\n")); + for (np = soap->nlist; np; np = nq) + { nq = np->next; + SOAP_FREE(soap, np); + } + soap->nlist = NULL; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free any remaining temp blocks\n")); + while (soap->blist) + soap_end_block(soap); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute storage\n")); + for (tp = soap->attributes; tp; tp = tq) + { tq = tp->next; + if (tp->value) + SOAP_FREE(soap, tp->value); + SOAP_FREE(soap, tp); + } + soap->attributes = NULL; +#ifdef WITH_FAST + if (soap->labbuf) + SOAP_FREE(soap, soap->labbuf); + soap->labbuf = NULL; + soap->lablen = 0; + soap->labidx = 0; +#endif + ns = soap->local_namespaces; + if (ns) + { for (; ns->id; ns++) + { if (ns->out) + { if (soap->encodingStyle == ns->out) + soap->encodingStyle = SOAP_STR_EOS; + SOAP_FREE(soap, ns->out); + ns->out = NULL; + } + if (soap->encodingStyle == ns->ns) + soap->encodingStyle = SOAP_STR_EOS; + } + SOAP_FREE(soap, soap->local_namespaces); + soap->local_namespaces = NULL; + } +#ifndef WITH_LEANER + while (soap->xlist) + { struct soap_xlist *xp = soap->xlist->next; + SOAP_FREE(soap, soap->xlist); + soap->xlist = xp; + } +#endif +#ifndef WITH_NOIDREF + soap_free_pht(soap); + soap_free_iht(soap); +#endif +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +static void +soap_init_logs(struct soap *soap) +{ int i; + for (i = 0; i < SOAP_MAXLOGS; i++) + { soap->logfile[i] = NULL; + soap->fdebug[i] = NULL; + } +} +#endif + +/******************************************************************************/ +#if !defined(WITH_LEAN) || defined(SOAP_DEBUG) +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_open_logfile(struct soap *soap, int i) +{ if (soap->logfile[i]) + soap->fdebug[i] = fopen(soap->logfile[i], i < 2 ? "ab" : "a"); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +static void +soap_close_logfile(struct soap *soap, int i) +{ if (soap->fdebug[i]) + { fclose(soap->fdebug[i]); + soap->fdebug[i] = NULL; + } +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_close_logfiles(struct soap *soap) +{ int i; + for (i = 0; i < SOAP_MAXLOGS; i++) + soap_close_logfile(soap, i); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +static void +soap_set_logfile(struct soap *soap, int i, const char *logfile) +{ const char *s; + char *t = NULL; + soap_close_logfile(soap, i); + s = soap->logfile[i]; + soap->logfile[i] = logfile; + if (s) + SOAP_FREE(soap, (void*)s); + if (logfile) + if ((t = (char*)SOAP_MALLOC(soap, strlen(logfile) + 1))) + strcpy(t, logfile); + soap->logfile[i] = t; +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_recv_logfile(struct soap *soap, const char *logfile) +{ soap_set_logfile(soap, SOAP_INDEX_RECV, logfile); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_sent_logfile(struct soap *soap, const char *logfile) +{ soap_set_logfile(soap, SOAP_INDEX_SENT, logfile); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_test_logfile(struct soap *soap, const char *logfile) +{ soap_set_logfile(soap, SOAP_INDEX_TEST, logfile); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_copy(const struct soap *soap) +{ return soap_copy_context((struct soap*)malloc(sizeof(struct soap)), soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_copy_context(struct soap *copy, const struct soap *soap) +{ if (soap_check_state(soap)) + return NULL; + if (copy) + { register struct soap_plugin *p = NULL; + memcpy(copy, soap, sizeof(struct soap)); + copy->state = SOAP_COPY; + copy->error = SOAP_OK; + copy->userid = NULL; + copy->passwd = NULL; + copy->nlist = NULL; + copy->blist = NULL; + copy->clist = NULL; + copy->alist = NULL; + copy->attributes = NULL; + copy->labbuf = NULL; + copy->lablen = 0; + copy->labidx = 0; +#ifdef SOAP_MEM_DEBUG + soap_init_mht(copy); +#endif +#ifdef SOAP_DEBUG + soap_init_logs(copy); + soap_set_recv_logfile(copy, soap->logfile[SOAP_INDEX_RECV]); + soap_set_sent_logfile(copy, soap->logfile[SOAP_INDEX_SENT]); + soap_set_test_logfile(copy, soap->logfile[SOAP_INDEX_TEST]); +#endif +#ifdef WITH_ZLIB + copy->d_stream = (z_stream*)SOAP_MALLOC(copy, sizeof(z_stream)); + copy->d_stream->zalloc = Z_NULL; + copy->d_stream->zfree = Z_NULL; + copy->d_stream->opaque = Z_NULL; + copy->z_buf = NULL; +#endif + copy->local_namespaces = NULL; +#ifndef WITH_NOIDREF + soap_init_iht(copy); + soap_init_pht(copy); +#endif + copy->header = NULL; + copy->fault = NULL; + copy->action = NULL; +#ifndef WITH_LEAN +#ifdef WITH_COOKIES + copy->cookies = soap_copy_cookies(copy, soap); +#else + copy->cookies = NULL; +#endif +#endif + copy->plugins = NULL; + for (p = soap->plugins; p; p = p->next) + { register struct soap_plugin *q = (struct soap_plugin*)SOAP_MALLOC(copy, sizeof(struct soap_plugin)); + if (!q) + return NULL; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying plugin '%s'\n", p->id)); + *q = *p; + if (p->fcopy && p->fcopy(copy, q, p)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not copy plugin '%s'\n", p->id)); + SOAP_FREE(copy, q); + return NULL; + } + q->next = copy->plugins; + copy->plugins = q; + } + } + return copy; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_copy_stream(struct soap *copy, struct soap *soap) +{ copy->mode = soap->mode; + copy->imode = soap->imode; + copy->omode = soap->omode; + copy->socket = soap->socket; + copy->recv_timeout = soap->recv_timeout; + copy->send_timeout = soap->send_timeout; +#if defined(__cplusplus) && !defined(WITH_LEAN) + copy->os = soap->os; + copy->is = soap->is; +#endif + copy->sendfd = soap->sendfd; + copy->recvfd = soap->recvfd; + copy->bufidx = soap->bufidx; + copy->buflen = soap->buflen; + copy->ahead = soap->ahead; + copy->cdata = soap->cdata; + copy->chunksize = soap->chunksize; + copy->chunkbuflen = soap->chunkbuflen; + copy->keep_alive = soap->keep_alive; + copy->tcp_keep_alive = soap->tcp_keep_alive; + copy->tcp_keep_idle = soap->tcp_keep_idle; + copy->tcp_keep_intvl = soap->tcp_keep_intvl; + copy->tcp_keep_cnt = soap->tcp_keep_cnt; + copy->max_keep_alive = soap->max_keep_alive; +#ifndef WITH_NOIO + copy->peer = soap->peer; + copy->peerlen = soap->peerlen; +#endif +#ifdef WITH_OPENSSL + copy->bio = soap->bio; + copy->ssl = soap->ssl; + copy->ctx = soap->ctx; +#endif +#ifdef WITH_ZLIB + copy->zlib_state = soap->zlib_state; + copy->zlib_in = soap->zlib_in; + copy->zlib_out = soap->zlib_out; + copy->d_stream = (z_stream*)SOAP_MALLOC(copy, sizeof(z_stream)); + memcpy(copy->d_stream, soap->d_stream, sizeof(z_stream)); + copy->z_crc = soap->z_crc; + copy->z_ratio_in = soap->z_ratio_in; + copy->z_ratio_out = soap->z_ratio_out; + copy->z_buf = NULL; + copy->z_buflen = soap->z_buflen; + copy->z_level = soap->z_level; + if (soap->z_buf && soap->zlib_state != SOAP_ZLIB_NONE) + { copy->z_buf = (char*)SOAP_MALLOC(copy, SOAP_BUFLEN); + memcpy(copy->z_buf, soap->z_buf, sizeof(soap->z_buf)); + } +#endif + memcpy(copy->buf, soap->buf, sizeof(soap->buf)); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_init(struct soap *soap) +{ soap->state = SOAP_INIT; +#ifdef SOAP_MEM_DEBUG + soap_init_mht(soap); +#endif + soap->version = 0; + soap_imode(soap, SOAP_IO_DEFAULT); + soap_omode(soap, SOAP_IO_DEFAULT); + soap->plugins = NULL; + soap->user = NULL; + soap->userid = NULL; + soap->passwd = NULL; +#ifndef WITH_NOHTTP + soap->fpost = http_post; + soap->fget = http_get; + soap->fput = http_put; + soap->fdel = http_del; + soap->fhead = http_head; + soap->fform = NULL; + soap->fposthdr = http_post_header; + soap->fresponse = http_response; + soap->fparse = http_parse; + soap->fparsehdr = http_parse_header; +#endif + soap->fheader = NULL; + soap->fconnect = NULL; + soap->fdisconnect = NULL; +#ifndef WITH_NOIO +#ifndef WITH_IPV6 + soap->fresolve = tcp_gethost; +#else + soap->fresolve = NULL; +#endif + soap->faccept = tcp_accept; + soap->fopen = tcp_connect; + soap->fclose = tcp_disconnect; + soap->fclosesocket = tcp_closesocket; + soap->fshutdownsocket = tcp_shutdownsocket; + soap->fsend = fsend; + soap->frecv = frecv; + soap->fpoll = soap_poll; +#else + soap->fopen = NULL; + soap->fclose = NULL; + soap->fpoll = NULL; +#endif + soap->fseterror = NULL; + soap->fignore = NULL; + soap->fserveloop = NULL; + soap->fplugin = fplugin; + soap->fmalloc = NULL; +#ifndef WITH_LEANER + soap->fprepareinit = NULL; + soap->fpreparesend = NULL; + soap->fpreparerecv = NULL; + soap->fpreparefinal = NULL; + soap->fdimereadopen = NULL; + soap->fdimewriteopen = NULL; + soap->fdimereadclose = NULL; + soap->fdimewriteclose = NULL; + soap->fdimeread = NULL; + soap->fdimewrite = NULL; + soap->fmimereadopen = NULL; + soap->fmimewriteopen = NULL; + soap->fmimereadclose = NULL; + soap->fmimewriteclose = NULL; + soap->fmimeread = NULL; + soap->fmimewrite = NULL; +#endif + soap->float_format = "%.9G"; /* Alternative: use "%G" */ + soap->double_format = "%.17lG"; /* Alternative: use "%lG" */ + soap->dime_id_format = "cid:id%d"; /* default DIME id format */ + soap->http_version = "1.1"; + soap->proxy_http_version = "1.0"; + soap->http_content = NULL; + soap->actor = NULL; + soap->keep_alive = 0; + soap->tcp_keep_alive = 0; + soap->tcp_keep_idle = 0; + soap->tcp_keep_intvl = 0; + soap->tcp_keep_cnt = 0; + soap->max_keep_alive = SOAP_MAXKEEPALIVE; + soap->recv_timeout = 0; + soap->send_timeout = 0; + soap->connect_timeout = 0; + soap->accept_timeout = 0; + soap->socket_flags = 0; + soap->connect_flags = 0; + soap->bind_flags = 0; + soap->accept_flags = 0; + soap->ip = 0; + soap->labbuf = NULL; + soap->lablen = 0; + soap->labidx = 0; + soap->encodingStyle = SOAP_STR_EOS; +#ifndef WITH_NONAMESPACES + soap->namespaces = namespaces; +#else + soap->namespaces = NULL; +#endif + soap->local_namespaces = NULL; + soap->nlist = NULL; + soap->blist = NULL; + soap->clist = NULL; + soap->alist = NULL; + soap->attributes = NULL; + soap->header = NULL; + soap->fault = NULL; + soap->master = SOAP_INVALID_SOCKET; + soap->socket = SOAP_INVALID_SOCKET; + soap->os = NULL; + soap->is = NULL; +#ifndef WITH_LEANER + soap->dom = NULL; + soap->dime.list = NULL; + soap->dime.first = NULL; + soap->dime.last = NULL; + soap->mime.list = NULL; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = NULL; + soap->mime.start = NULL; + soap->xlist = NULL; +#endif +#ifndef UNDER_CE + soap->recvfd = 0; + soap->sendfd = 1; +#else + soap->recvfd = stdin; + soap->sendfd = stdout; +#endif + soap->host[0] = '\0'; + soap->port = 0; + soap->action = NULL; + soap->proxy_host = NULL; + soap->proxy_port = 8080; + soap->proxy_userid = NULL; + soap->proxy_passwd = NULL; + soap->authrealm = NULL; + soap->prolog = NULL; +#ifdef WITH_ZLIB + soap->zlib_state = SOAP_ZLIB_NONE; + soap->zlib_in = SOAP_ZLIB_NONE; + soap->zlib_out = SOAP_ZLIB_NONE; + soap->d_stream = (z_stream*)SOAP_MALLOC(soap, sizeof(z_stream)); + soap->d_stream->zalloc = Z_NULL; + soap->d_stream->zfree = Z_NULL; + soap->d_stream->opaque = Z_NULL; + soap->z_buf = NULL; + soap->z_level = 6; +#endif +#ifndef WITH_LEAN + soap->c14ninclude = NULL; + soap->c14nexclude = NULL; + soap->cookies = NULL; + soap->cookie_domain = NULL; + soap->cookie_path = NULL; + soap->cookie_max = 32; +#endif +#ifdef SOAP_DEBUG + soap_init_logs(soap); +#endif +#ifdef WMW_RPM_IO + soap->rpmreqid = NULL; +#endif +#ifdef PALM + palmNetLibOpen(); +#endif +#ifndef WITH_NOIDREF + soap_init_iht(soap); + soap_init_pht(soap); +#endif +#ifdef SOAP_DEBUG + soap_set_recv_logfile(soap, "RECV.log"); + soap_set_sent_logfile(soap, "SENT.log"); + soap_set_test_logfile(soap, "TEST.log"); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing context\n")); +#endif +#ifdef WITH_OPENSSL + if (!soap_ssl_init_done) + { soap_ssl_init(); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing OpenSSL, version=%ld\n", (long)OPENSSL_VERSION_NUMBER)); + } + soap->fsslauth = ssl_auth_init; + soap->fsslverify = ssl_verify_callback; + soap->bio = NULL; + soap->ssl = NULL; + soap->ctx = NULL; + soap->ssl_flags = SOAP_SSL_DEFAULT; + soap->keyfile = NULL; + soap->password = NULL; + soap->dhfile = NULL; + soap->cafile = NULL; + soap->capath = NULL; + soap->crlfile = NULL; + soap->randfile = NULL; + soap->session = NULL; +#endif + soap_begin(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_init1(struct soap *soap, soap_mode mode) +{ soap_init2(soap, mode, mode); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_init2(struct soap *soap, soap_mode imode, soap_mode omode) +{ soap_init(soap); + soap_imode(soap, imode); + soap_omode(soap, omode); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_begin(struct soap *soap) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reinitializing context\n")); + if (!soap->keep_alive) + { soap->buflen = 0; + soap->bufidx = 0; + } + soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0); + soap->null = 0; + soap->position = 0; + soap->encoding = 0; + soap->mustUnderstand = 0; + soap->mode = 0; + soap->ns = 0; + soap->part = SOAP_END; + soap->alloced = 0; + soap->count = 0; + soap->length = 0; + soap->cdata = 0; + soap->error = SOAP_OK; + soap->peeked = 0; + soap->ahead = 0; + soap->idnum = 0; + soap->level = 0; + soap->endpoint[0] = '\0'; +#ifndef WITH_LEANER + soap->dime.chunksize = 0; + soap->dime.buflen = 0; +#endif + soap_free_temp(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_end(struct soap *soap) +{ if (soap_check_state(soap)) + return; + soap_free_temp(soap); + soap_dealloc(soap, NULL); + while (soap->clist) + { register struct soap_clist *cp = soap->clist->next; + SOAP_FREE(soap, soap->clist); + soap->clist = cp; + } + soap_closesock(soap); +#ifdef SOAP_DEBUG + soap_close_logfiles(soap); +#endif +#ifdef PALM + palmNetLibClose(); +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_namespaces(struct soap *soap, const struct Namespace *p) +{ register struct Namespace *ns = soap->local_namespaces; + register struct soap_nlist *np, *nq, *nr; + register unsigned int level = soap->level; + soap->namespaces = p; + soap->local_namespaces = NULL; + soap_set_local_namespaces(soap); + /* reverse the namespace list */ + np = soap->nlist; + soap->nlist = NULL; + if (np) + { nq = np->next; + np->next = NULL; + while (nq) + { nr = nq->next; + nq->next = np; + np = nq; + nq = nr; + } + } + /* then push on new stack */ + while (np) + { register const char *s; + soap->level = np->level; /* preserve element nesting level */ + s = np->ns; + if (!s && np->index >= 0 && ns) + { s = ns[np->index].out; + if (!s) + s = ns[np->index].ns; + } + if (s && soap_push_namespace(soap, np->id, s)) + return soap->error; + nq = np; + np = np->next; + SOAP_FREE(soap, nq); + } + if (ns) + { register int i; + for (i = 0; ns[i].id; i++) + { if (ns[i].out) + { SOAP_FREE(soap, ns[i].out); + ns[i].out = NULL; + } + } + SOAP_FREE(soap, ns); + } + soap->level = level; /* restore level */ + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_local_namespaces(struct soap *soap) +{ if (soap->namespaces && !soap->local_namespaces) + { register const struct Namespace *ns1; + register struct Namespace *ns2; + register size_t n = 1; + for (ns1 = soap->namespaces; ns1->id; ns1++) + n++; + n *= sizeof(struct Namespace); + ns2 = (struct Namespace*)SOAP_MALLOC(soap, n); + if (ns2) + { memcpy(ns2, soap->namespaces, n); + if (ns2[0].ns) + { if (!strcmp(ns2[0].ns, soap_env1)) + soap->version = 1; + else + soap->version = 2; + } + soap->local_namespaces = ns2; + } + } +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +#ifndef PALM_1 +SOAP_FMAC1 +const char * +SOAP_FMAC2 +soap_strsearch(const char *big, const char *little) +{ size_t n = strlen(little); + const char *s = big; + while (s) + { if (!strncmp(s, little, n) && (s[n] == '\0' || s[n] == ' ')) + return s; + s = strchr(s, ' '); + if (s) + s++; + } + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +#ifndef PALM_1 +SOAP_FMAC1 +struct soap_nlist * +SOAP_FMAC2 +soap_lookup_ns(struct soap *soap, const char *tag, size_t n) +{ register struct soap_nlist *np; + for (np = soap->nlist; np; np = np->next) + { if (!strncmp(np->id, tag, n) && !np->id[n]) + return np; + } + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static struct soap_nlist * +soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized) +{ register struct soap_nlist *np; + size_t n, k; + if (soap_strsearch(soap->c14nexclude, id)) + return NULL; + if (!utilized) + { for (np = soap->nlist; np; np = np->next) + { if (!strcmp(np->id, id) && (!np->ns || !strcmp(np->ns, ns))) + break; + } + if (np) + { if ((np->level < soap->level || !np->ns) && np->index == 1) + utilized = 1; + else + return NULL; + } + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Adding namespace binding (level=%u) '%s' '%s' utilized=%d\n", soap->level, id, ns?ns:"(null)", utilized)); + n = strlen(id); + if (ns) + k = strlen(ns); + else + k = 0; + np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k + 1); + if (!np) + { soap->error = SOAP_EOM; + return NULL; + } + np->next = soap->nlist; + soap->nlist = np; + strcpy(np->id, id); + if (ns) + { np->ns = np->id + n + 1; + strcpy(np->ns, ns); + } + else + np->ns = NULL; + np->level = soap->level; + np->index = utilized; + return np; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static void +soap_utilize_ns(struct soap *soap, const char *tag, size_t n) +{ register struct soap_nlist *np = soap_lookup_ns(soap, tag, n); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Utilizing namespace of '%s'\n", tag)); + if (np) + { if (np->index == 0) + soap_push_ns(soap, np->id, np->ns, 1); + } + else if (strncmp(tag, "xml", 3)) + { strncpy(soap->tmpbuf, tag, n); + soap->tmpbuf[n] = '\0'; + soap_push_ns(soap, soap->tmpbuf, NULL, 1); + } +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static void +soap_pop_ns(struct soap *soap) +{ soap_pop_namespace(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element(struct soap *soap, const char *tag, int id, const char *type) +{ +#ifdef WITH_XMLNS + register const char *s; +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element begin tag='%s' id='%d' type='%s'\n", tag, id, type?type:"")); +#ifdef WITH_DOM + if (soap->part == SOAP_BEGIN_SECURITY && (soap->mode & SOAP_XML_CANONICAL) && !(soap->mode & SOAP_DOM_ASIS)) + { register struct soap_nlist *np; + /* wsu:Id found: clear xmlns renderings, so re-emit them for exc-c14n */ + for (np = soap->nlist; np; np = np->next) + { if (np->index == 2) + np->index = 0; + } + } + if (soap->mode & SOAP_XML_DOM) + { register struct soap_dom_element *elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element)); + if (!elt) + return soap->error = SOAP_EOM; + elt->soap = soap; + elt->next = NULL; + elt->prnt = soap->dom; + elt->name = soap_strdup(soap, tag); + elt->elts = NULL; + elt->atts = NULL; + elt->nstr = NULL; + elt->data = NULL; + elt->wide = NULL; + elt->node = NULL; + elt->type = 0; + elt->head = NULL; + elt->tail = NULL; + if (soap->dom) + { struct soap_dom_element *p = soap->dom->elts; + if (p) + { while (p->next) + p = p->next; + p->next = elt; + } + else + soap->dom->elts = elt; + } + soap->dom = elt; + } + else + { +#endif + soap->level++; +#ifndef WITH_LEAN + if (!soap->ns) + { if (!(soap->mode & SOAP_XML_CANONICAL) + && soap_send(soap, soap->prolog ? soap->prolog : "\n")) + return soap->error; + } + else if (soap->mode & SOAP_XML_INDENT) + { if (soap->ns == 1 && soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1)) + return soap->error; + soap->body = 1; + } +#endif +#ifdef WITH_XMLNS + s = strchr(tag, ':'); + if (s && strncmp(tag, "SOAP-ENV", s - tag)) + { struct Namespace *ns = soap->local_namespaces; + size_t n = s - tag; + if (soap_send_raw(soap, "<", 1) + || soap_send(soap, s + 1)) + return soap->error; + if (soap->nlist && !strncmp(soap->nlist->id, tag, n) && !soap->nlist->id[n]) + ns = NULL; + for (; ns && ns->id; ns++) + { if (*ns->id && (ns->out || ns->ns) && !strncmp(ns->id, tag, n) && !ns->id[n]) + { soap_push_ns(soap, ns->id, ns->out ? ns->out : ns->ns, 0); + if (soap_attribute(soap, "xmlns", ns->out ? ns->out : ns->ns)) + return soap->error; + break; + } + } + } + else +#endif + if (soap_send_raw(soap, "<", 1) + || soap_send(soap, tag)) + return soap->error; +#ifdef WITH_DOM + } +#endif + if (!soap->ns) + { struct Namespace *ns; + for (ns = soap->local_namespaces; ns && ns->id; ns++) + { if (*ns->id && (ns->out || ns->ns)) + { sprintf(soap->tmpbuf, "xmlns:%s", ns->id); + if (soap_attribute(soap, soap->tmpbuf, ns->out ? ns->out : ns->ns)) + return soap->error; + } + } + } + soap->ns = 1; /* start with 0 or 2, but should be one to continue */ +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { const char *t = strchr(tag, ':'); + if (t) + soap_utilize_ns(soap, tag, t - tag); + } +#endif + if (id > 0) + { sprintf(soap->tmpbuf, "_%d", id); + if (soap_attribute(soap, "id", soap->tmpbuf)) + return soap->error; + } + if (type && *type && (!(soap->mode & SOAP_XML_SEC) || soap->part == SOAP_IN_BODY)) + { if (soap_attribute(soap, "xsi:type", type)) + return soap->error; +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { const char *t = strchr(type, ':'); + if (t) + soap_utilize_ns(soap, type, t - type); + } +#endif + } + if (soap->null && soap->position > 0) + { register int i; + sprintf(soap->tmpbuf, "[%d", soap->positions[0]); + for (i = 1; i < soap->position; i++) + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), ",%d", soap->positions[i]); + strcat(soap->tmpbuf, "]"); + if (soap_attribute(soap, "SOAP-ENC:position", soap->tmpbuf)) + return soap->error; + } + if (soap->mustUnderstand) + { if (soap->actor && *soap->actor) + { if (soap_attribute(soap, soap->version == 2 ? "SOAP-ENV:role" : "SOAP-ENV:actor", soap->actor)) + return soap->error; + } + if (soap_attribute(soap, "SOAP-ENV:mustUnderstand", soap->version == 2 ? "true" : "1")) + return soap->error; + soap->mustUnderstand = 0; + } + if (soap->encoding) + { if (soap->encodingStyle && soap->local_namespaces) + { if (!*soap->encodingStyle) + { if (soap->local_namespaces[1].out) + soap->encodingStyle = soap->local_namespaces[1].out; + else + soap->encodingStyle = soap->local_namespaces[1].ns; + } + if (soap_attribute(soap, "SOAP-ENV:encodingStyle", soap->encodingStyle)) + return soap->error; + } + soap->encoding = 0; + } + soap->null = 0; + soap->position = 0; + if (soap->part == SOAP_BEGIN_SECURITY && (soap->mode & SOAP_XML_CANONICAL)) + soap->part = SOAP_IN_SECURITY; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_begin_out(struct soap *soap, const char *tag, int id, const char *type) +{ if (*tag == '-') + return SOAP_OK; + if (soap_element(soap, tag, id, type)) + return soap->error; + return soap_element_start_end_out(soap, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +#ifndef HAVE_STRRCHR +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_strrchr(const char *s, int t) +{ register char *r = NULL; + while (*s) + if (*s++ == t) + r = (char*)s - 1; + return r; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +#ifndef HAVE_STRTOL +SOAP_FMAC1 +long +SOAP_FMAC2 +soap_strtol(const char *s, char **t, int b) +{ register long n = 0; + register int c; + while (*s > 0 && *s <= 32) + s++; + if (b == 10) + { short neg = 0; + if (*s == '-') + { s++; + neg = 1; + } + else if (*s == '+') + s++; + while ((c = *s) && c >= '0' && c <= '9') + { if (n >= 214748364 && (n > 214748364 || c >= '8')) + break; + n *= 10; + n += c - '0'; + s++; + } + if (neg) + n = -n; + } + else /* b == 16 and value is always positive */ + { while ((c = *s)) + { if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'F') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'f') + c -= 'a' - 10; + if (n > 0x07FFFFFF) + break; + n <<= 4; + n += c; + s++; + } + } + if (t) + *t = (char*)s; + return n; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +#ifndef HAVE_STRTOUL +SOAP_FMAC1 +unsigned long +SOAP_FMAC2 +soap_strtoul(const char *s, char **t, int b) +{ unsigned long n = 0; + register int c; + while (*s > 0 && *s <= 32) + s++; + if (b == 10) + { if (*s == '+') + s++; + while ((c = *s) && c >= '0' && c <= '9') + { if (n >= 429496729 && (n > 429496729 || c >= '6')) + break; + n *= 10; + n += c - '0'; + s++; + } + } + else /* b == 16 */ + { while ((c = *s)) + { if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'F') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'f') + c -= 'a' - 10; + if (n > 0x0FFFFFFF) + break; + n <<= 4; + n += c; + s++; + } + } + if (t) + *t = (char*)s; + return n; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_array_begin_out(struct soap *soap, const char *tag, int id, const char *type, const char *offset) +{ if (soap_element(soap, tag, id, "SOAP-ENC:Array")) + return soap->error; + if (soap->version == 2) + { const char *s; + s = soap_strrchr(type, '['); + if ((size_t)(s - type) < sizeof(soap->tmpbuf)) + { strncpy(soap->tmpbuf, type, s - type); + soap->tmpbuf[s - type] = '\0'; + if (type && *type && (soap_attribute(soap, "SOAP-ENC:itemType", soap->tmpbuf))) + return soap->error; + if (s && (soap_attribute(soap, "SOAP-ENC:arraySize", s + 1))) + return soap->error; + } + } + else + { if (offset && (soap_attribute(soap, "SOAP-ENC:offset", offset))) + return soap->error; + if (type && *type && (soap_attribute(soap, "SOAP-ENC:arrayType", type))) + return soap->error; + } +#ifndef WITH_LEAN + if (type && *type && (soap->mode & SOAP_XML_CANONICAL)) + { const char *s = strchr(type, ':'); + if (s) + soap_utilize_ns(soap, type, s - type); + } +#endif + return soap_element_start_end_out(soap, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_start_end_out(struct soap *soap, const char *tag) +{ register struct soap_attribute *tp; +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { struct soap_nlist *np; + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible && tp->name) + { const char *s = strchr(tp->name, ':'); + if (s) + soap_utilize_ns(soap, tp->name, s - tp->name); + } + } + for (np = soap->nlist; np; np = np->next) + { if (np->index == 1 && np->ns) + { sprintf(soap->tmpbuf, "xmlns:%s", np->id); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enabling utilized binding (level=%u) %s='%s'\n", np->level, soap->tmpbuf, np->ns)); + soap_set_attr(soap, soap->tmpbuf, np->ns); + np->index = 2; + } + } + } +#endif +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { register struct soap_dom_attribute **att; + att = &soap->dom->atts; + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible) + { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); + if (!*att) + return soap->error = SOAP_EOM; + (*att)->next = NULL; + (*att)->nstr = NULL; + (*att)->name = soap_strdup(soap, tp->name); + (*att)->data = soap_strdup(soap, tp->value); + (*att)->wide = NULL; + (*att)->soap = soap; + att = &(*att)->next; + tp->visible = 0; + } + } + return SOAP_OK; + } +#endif + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible) + { +#ifdef WITH_XMLNS + const char *s = strchr(tp->name, ':'); + if (s) + { size_t n = s - tp->name; + if (soap->nlist && !strncmp(soap->nlist->id, tp->name, n) && !soap->nlist->id[n]) + s++; + else + s = tp->name; + if (soap_send(soap, " ") || soap_send(soap, s)) + return soap->error; + } + else +#endif + if (soap_send(soap, " ") || soap_send(soap, tp->name)) + return soap->error; + if (tp->visible == 2 && tp->value) + if (soap_send_raw(soap, "=\"", 2) + || soap_string_out(soap, tp->value, 1) + || soap_send_raw(soap, "\"", 1)) + return soap->error; + tp->visible = 0; + } + } + if (tag) + { +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { if (soap_send_raw(soap, ">", 1) + || soap_element_end_out(soap, tag)) + return soap->error; + return SOAP_OK; + } +#endif + soap->level--; /* decrement level just before /> */ + if (soap_send_raw(soap, "/>", 2)) + return soap->error; + return SOAP_OK; + } + return soap_send_raw(soap, ">", 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_end_out(struct soap *soap, const char *tag) +{ if (*tag == '-') + return SOAP_OK; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element ending tag='%s'\n", tag)); +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { if (soap->dom->prnt) + soap->dom = soap->dom->prnt; + return SOAP_OK; + } +#endif +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + soap_pop_ns(soap); + if (soap->mode & SOAP_XML_INDENT) + { if (!soap->body) + { if (soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1)) + return soap->error; + } + soap->body = 0; + } +#endif +#ifdef WITH_XMLNS + { const char *s = strchr(tag, ':'); + if (s && strncmp(tag, "SOAP-ENV", s - tag)) + { soap_pop_ns(soap); + tag = s + 1; + } + } +#endif + if (soap_send_raw(soap, "error; + soap->level--; /* decrement level just before > */ + return soap_send_raw(soap, ">", 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_ref(struct soap *soap, const char *tag, int id, int href) +{ register int n = 0; + const char *s = "href"; + if (soap->version == 2) + { s = "SOAP-ENC:ref"; + n = 1; + } + sprintf(soap->href, "#_%d", href); + return soap_element_href(soap, tag, id, s, soap->href + n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_href(struct soap *soap, const char *tag, int id, const char *ref, const char *val) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element '%s' reference %s='%s'\n", tag, ref, val)); + if (soap_element(soap, tag, id, NULL) + || soap_attribute(soap, ref, val) + || soap_element_start_end_out(soap, tag)) + return soap->error; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_null(struct soap *soap, const char *tag, int id, const char *type) +{ struct soap_attribute *tp; + for (tp = soap->attributes; tp; tp = tp->next) + if (tp->visible) + break; + if (tp || (soap->version == 2 && soap->position > 0) || id > 0 || (soap->mode & SOAP_XML_NIL)) + { if (soap_element(soap, tag, id, type)) + return soap->error; + if (!tp && soap_attribute(soap, "xsi:nil", "true")) + return soap->error; + return soap_element_start_end_out(soap, tag); + } + soap->null = 1; + soap->position = 0; + soap->mustUnderstand = 0; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_id(struct soap *soap, const char *tag, int id, const void *p, const struct soap_array *a, int n, const char *type, int t) +{ if (!p || (a && !a->__ptr)) + { soap_element_null(soap, tag, id, type); + return -1; + } +#ifndef WITH_NOIDREF + if (soap->mode & SOAP_XML_TREE) + return 0; + if (id < 0) + { struct soap_plist *pp; + if (a) + id = soap_array_pointer_lookup(soap, p, a, n, t, &pp); + else + id = soap_pointer_lookup(soap, p, t, &pp); + if (id) + { if (soap_is_embedded(soap, pp)) + { soap_element_ref(soap, tag, 0, id); + return -1; + } + if (soap_is_single(soap, pp)) + return 0; + soap_set_embedded(soap, pp); + } + } + return id; +#else + return 0; +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_result(struct soap *soap, const char *tag) +{ if (soap->version == 2 && soap->encodingStyle) + { if (soap_element(soap, "SOAP-RPC:result", 0, NULL) + || soap_attribute(soap, "xmlns:SOAP-RPC", soap_rpc) + || soap_element_start_end_out(soap, NULL) + || soap_string_out(soap, tag, 0) + || soap_element_end_out(soap, "SOAP-RPC:result")) + return soap->error; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_check_result(struct soap *soap, const char *tag) +{ if (soap->version == 2 && soap->encodingStyle) + { soap_instring(soap, ":result", NULL, NULL, 0, 2, -1, -1); + /* just ignore content for compliance reasons, but should compare tag to element's QName value? */ + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_attribute(struct soap *soap, const char *name, const char *value) +{ +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && !(soap->mode & SOAP_XML_CANONICAL) && soap->dom) + { register struct soap_dom_attribute *a = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); + a->next = soap->dom->atts; + a->nstr = NULL; + a->name = soap_strdup(soap, name); + a->data = soap_strdup(soap, value); + a->wide = NULL; + a->soap = soap; + soap->dom->atts = a; + return SOAP_OK; + } +#endif +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { /* TODO: consider using this code to handle default namespace bindings + if (!strncmp(name, "xmlns", 5) && (name[5] == ':' || name[5] == '\0')) + { if (name[5] == ':') + soap_push_ns(soap, name + 6, value, 0); + else + soap_push_ns(soap, "", value, 0); + } + */ + if (!strncmp(name, "xmlns:", 6)) + soap_push_ns(soap, name + 6, value, 0); + else if (soap_set_attr(soap, name, value)) + return soap->error; + } + else +#endif + { if (soap_send(soap, " ") || soap_send(soap, name)) + return soap->error; + if (value) + if (soap_send_raw(soap, "=\"", 2) + || soap_string_out(soap, value, 1) + || soap_send_raw(soap, "\"", 1)) + return soap->error; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_begin_in(struct soap *soap, const char *tag, int nillable, const char *type) +{ if (!soap_peek_element(soap)) + { if (soap->other) + return soap->error = SOAP_TAG_MISMATCH; + if (tag && *tag == '-') + return SOAP_OK; + if (!(soap->error = soap_match_tag(soap, soap->tag, tag))) + { soap->peeked = 0; + if (type && *soap->type && soap_match_tag(soap, soap->type, type)) + return soap->error = SOAP_TYPE; + if (!nillable && soap->null && (soap->mode & SOAP_XML_STRICT)) + return soap->error = SOAP_NULL; + if (soap->body) + soap->level++; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:"" )); + } + } + else if (soap->error == SOAP_NO_TAG && tag && *tag == '-') + soap->error = SOAP_OK; + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_end_in(struct soap *soap, const char *tag) +{ register soap_wchar c; + register char *s; + register int n = 0; + if (tag && *tag == '-') + return SOAP_OK; + if (soap->error == SOAP_NO_TAG) + soap->error = SOAP_OK; +#ifdef WITH_DOM + /* this whitespace or mixed content is not insignificant for DOM */ + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { if (!soap->peeked && !soap_string_in(soap, 3, -1, -1)) + return soap->error; + if (soap->dom->prnt) + soap->dom = soap->dom->prnt; + } +#endif + if (soap->peeked) + { if (*soap->tag) + n++; + soap->peeked = 0; + } + do + { while (((c = soap_get(soap)) != SOAP_TT)) + { if ((int)c == EOF) + return soap->error = SOAP_EOF; + if (c == SOAP_LT) + n++; + else if (c == '/') + { c = soap_get(soap); + if (c == SOAP_GT) + n--; + else + soap_unget(soap, c); + } + } + } while (n--); + s = soap->tag; + n = sizeof(soap->tag); + while (soap_notblank(c = soap_get(soap))) + { if (--n > 0) + *s++ = (char)c; + } + *s = '\0'; + if ((int)c == EOF) + return soap->error = SOAP_EOF; + while (soap_blank(c)) + c = soap_get(soap); + if (c != SOAP_GT) + return soap->error = SOAP_SYNTAX_ERROR; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:"")); +#ifndef WITH_LEAN + if (tag && (soap->mode & SOAP_XML_STRICT)) + { soap_pop_namespace(soap); + if (soap_match_tag(soap, soap->tag, tag)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element tag name does not match\n")); + return soap->error = SOAP_SYNTAX_ERROR; + } + } +#endif + soap->level--; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char * +SOAP_FMAC2 +soap_attr_value(struct soap *soap, const char *name, int flag) +{ register struct soap_attribute *tp; + if (*name == '-') + return SOAP_STR_EOS; + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible && !soap_match_tag(soap, tp->name, name)) + break; + } + if (tp) + { if (flag == 2 && (soap->mode & SOAP_XML_STRICT)) + soap->error = SOAP_PROHIBITED; + else + return tp->value; + } + else if (flag == 1 && (soap->mode & SOAP_XML_STRICT)) + soap->error = SOAP_REQUIRED; + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_attr(struct soap *soap, const char *name, const char *value) +{ register struct soap_attribute *tp; + if (*name == '-') + return SOAP_OK; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set attribute %s='%s'\n", name, value?value:"")); + for (tp = soap->attributes; tp; tp = tp->next) + { if (!strcmp(tp->name, name)) + break; + } + if (!tp) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute %s\n", name)); + if (!(tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(name)))) + return soap->error = SOAP_EOM; + tp->ns = NULL; +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { struct soap_attribute **tpp = &soap->attributes; + const char *s = strchr(name, ':'); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inserting attribute %s for c14n\n", name)) + if (!strncmp(name, "xmlns", 5)) + { for (; *tpp; tpp = &(*tpp)->next) + if (strncmp((*tpp)->name, "xmlns", 5) || strcmp((*tpp)->name + 5, name + 5) > 0) + break; + } + else if (!s) + { for (; *tpp; tpp = &(*tpp)->next) + if (strncmp((*tpp)->name, "xmlns", 5) && ((*tpp)->ns || strcmp((*tpp)->name, name) > 0)) + break; + } + else + { int k; + for (; *tpp; tpp = &(*tpp)->next) + { if (!strncmp((*tpp)->name, "xmlns:", 6) && !strncmp((*tpp)->name + 6, name, s - name) && !(*tpp)->name[6 + s - name]) + { if (!tp->ns) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Canonicalization: prefix %s=%p (%s)\n", name, (*tpp)->ns, (*tpp)->ns)); + tp->ns = (*tpp)->ns; + } + } + else if (strncmp((*tpp)->name, "xmlns", 5) && (*tpp)->ns && tp->ns && ((k = strcmp((*tpp)->ns, tp->ns)) > 0 || (!k && strcmp((*tpp)->name, name) > 0))) + break; + } + } + tp->next = *tpp; + *tpp = tp; + } + else +#endif + { tp->next = soap->attributes; + soap->attributes = tp; + } + strcpy(tp->name, name); + tp->value = NULL; + } + else if (tp->visible) + { return SOAP_OK; + } + else if (value && tp->value && tp->size <= strlen(value)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute value of %s (free %p)\n", name, tp->value)); + SOAP_FREE(soap, tp->value); + tp->value = NULL; + tp->ns = NULL; + } + if (value) + { if (!tp->value) + { tp->size = strlen(value) + 1; + if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size))) + return soap->error = SOAP_EOM; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute value for %s (%p)\n", tp->name, tp->value)); + } + strcpy(tp->value, value); + if (!strncmp(tp->name, "xmlns:", 6)) + tp->ns = tp->value; + tp->visible = 2; +#ifndef WITH_LEAN + if (!strcmp(name, "wsu:Id")) + { soap->part = SOAP_BEGIN_SECURITY; + strncpy(soap->id, value, sizeof(soap->id)); + soap->id[sizeof(soap->id)-1] = '\0'; + } +#endif + } + else + tp->visible = 1; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_clr_attr(struct soap *soap) +{ register struct soap_attribute *tp; +#ifndef WITH_LEAN + if ((soap->mode & SOAP_XML_CANONICAL)) + { while (soap->attributes) + { tp = soap->attributes->next; + if (soap->attributes->value) + SOAP_FREE(soap, soap->attributes->value); + SOAP_FREE(soap, soap->attributes); + soap->attributes = tp; + } + } + else +#endif + { for (tp = soap->attributes; tp; tp = tp->next) + tp->visible = 0; + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +static int +soap_getattrval(struct soap *soap, char *s, size_t n, soap_wchar d) +{ register size_t i; + for (i = 0; i < n; i++) + { register soap_wchar c = soap_get(soap); + switch (c) + { + case SOAP_TT: + *s++ = '<'; + soap_unget(soap, '/'); + break; + case SOAP_LT: + *s++ = '<'; + break; + case SOAP_GT: + if (d == ' ') + { soap_unget(soap, c); + *s = '\0'; + return SOAP_OK; + } + *s++ = '>'; + break; + case SOAP_QT: + if (c == d) + { *s = '\0'; + return SOAP_OK; + } + *s++ = '"'; + break; + case SOAP_AP: + if (c == d) + { *s = '\0'; + return SOAP_OK; + } + *s++ = '\''; + break; + case '\t': + case '\n': + case '\r': + case ' ': + case '/': + if (d == ' ') + { soap_unget(soap, c); + *s = '\0'; + return SOAP_OK; + } + default: + if ((int)c == EOF) + return soap->error = SOAP_EOF; + *s++ = (char)c; + } + } + return soap->error = SOAP_EOM; +} +#endif + +/******************************************************************************/ +#ifdef WITH_FAST +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_store_lab(struct soap *soap, const char *s, size_t n) +{ soap->labidx = 0; + return soap_append_lab(soap, s, n); +} +#endif +#endif + +/******************************************************************************/ +#ifdef WITH_FAST +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_append_lab(struct soap *soap, const char *s, size_t n) +{ if (soap->labidx + n >= soap->lablen) + { register char *t = soap->labbuf; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enlarging look-aside buffer to append data, old size=%lu", (unsigned long)soap->lablen)); + if (soap->lablen == 0) + soap->lablen = SOAP_LABLEN; + while (soap->labidx + n >= soap->lablen) + soap->lablen <<= 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, ", new size=%lu\n", (unsigned long)soap->lablen)); + soap->labbuf = (char*)SOAP_MALLOC(soap, soap->lablen); + if (!soap->labbuf) + { if (t) + SOAP_FREE(soap, t); + return soap->error = SOAP_EOM; + } + if (t) + { memcpy(soap->labbuf, t, soap->labidx); + SOAP_FREE(soap, t); + } + } + if (s) + { memcpy(soap->labbuf + soap->labidx, s, n); + soap->labidx += n; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_peek_element(struct soap *soap) +{ +#ifdef WITH_DOM + register struct soap_dom_attribute **att = NULL; + register char *lead = NULL; +#endif + register struct soap_attribute *tp, *tq = NULL; + const char *t; + register char *s; + register soap_wchar c; + register int i; + if (soap->peeked) + { if (!*soap->tag) + return soap->error = SOAP_NO_TAG; + return SOAP_OK; + } + soap->peeked = 1; + soap->id[0] = '\0'; + soap->href[0] = '\0'; + soap->type[0] = '\0'; + soap->arrayType[0] = '\0'; + soap->arraySize[0] = '\0'; + soap->arrayOffset[0] = '\0'; + soap->other = 0; + soap->root = -1; + soap->position = 0; + soap->null = 0; + soap->mustUnderstand = 0; + c = soap_getutf8(soap); +#ifdef WITH_DOM + /* whitespace leading to start tag is not insignificant for DOM */ + if (soap_blank(c)) + { soap->labidx = 0; + do + { if (soap_append_lab(soap, NULL, 0)) + return SOAP_EOM; + s = soap->labbuf + soap->labidx; + i = soap->lablen - soap->labidx; + soap->labidx = soap->lablen; + while (soap_blank(c) && i--) + { *s++ = c; + c = soap_getutf8(soap); + } + } + while (soap_blank(c)); + *s = '\0'; + lead = soap_strdup(soap, soap->labbuf); + } +#else + while (soap_blank(c)) + c = soap_getutf8(soap); +#endif + if (c != SOAP_LT) + { *soap->tag = '\0'; + if ((int)c == EOF) + return soap->error = SOAP_EOF; + soap_unget(soap, c); +#ifdef WITH_DOM + /* whitespace leading to end tag is not insignificant for DOM */ + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + soap->dom->tail = soap_strdup(soap, lead); +#endif + return soap->error = SOAP_NO_TAG; + } + s = soap->tag; + do c = soap_get1(soap); + while (soap_blank(c)); + i = sizeof(soap->tag); + while (c != '>' && c != '/' && soap_notblank(c) && (int)c != EOF) + { if (--i > 0) + *s++ = (char)c; + c = soap_get1(soap); + } + while (soap_blank(c)) + c = soap_get1(soap); + *s = '\0'; +#ifdef WITH_DOM + if (soap->mode & SOAP_XML_DOM) + { register struct soap_dom_element *elt; + elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element)); + if (!elt) + return soap->error = SOAP_EOM; + elt->next = NULL; + elt->nstr = NULL; + elt->name = soap_strdup(soap, soap->tag); + elt->prnt = soap->dom; + elt->elts = NULL; + elt->atts = NULL; + elt->data = NULL; + elt->wide = NULL; + elt->type = 0; + elt->node = NULL; + elt->head = lead; + elt->tail = NULL; + elt->soap = soap; + if (soap->dom) + { struct soap_dom_element *p = soap->dom->elts; + if (p) + { while (p->next) + p = p->next; + p->next = elt; + } + else + soap->dom->elts = elt; + } + soap->dom = elt; + att = &elt->atts; + } +#endif + soap_pop_namespace(soap); + for (tp = soap->attributes; tp; tp = tp->next) + tp->visible = 0; + while ((int)c != EOF && c != '>' && c != '/') + { s = soap->tmpbuf; + i = sizeof(soap->tmpbuf); + while (c != '=' && c != '>' && c != '/' && soap_notblank(c) && (int)c != EOF) + { if (--i > 0) + *s++ = (char)c; + c = soap_get1(soap); + } + *s = '\0'; + if (i == sizeof(soap->tmpbuf)) + return soap->error = SOAP_SYNTAX_ERROR; +#ifdef WITH_DOM + /* add attribute name to dom */ + if (att) + { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); + if (!*att) + return soap->error = SOAP_EOM; + (*att)->next = NULL; + (*att)->nstr = NULL; + (*att)->name = soap_strdup(soap, soap->tmpbuf); + (*att)->data = NULL; + (*att)->wide = NULL; + (*att)->soap = soap; + } +#endif + if (!strncmp(soap->tmpbuf, "xmlns", 5)) + { if (soap->tmpbuf[5] == ':') + t = soap->tmpbuf + 6; + else if (soap->tmpbuf[5]) + t = NULL; + else + t = SOAP_STR_EOS; + } + else + t = NULL; + tq = NULL; + for (tp = soap->attributes; tp; tq = tp, tp = tp->next) + { if (!SOAP_STRCMP(tp->name, soap->tmpbuf)) + break; + } + if (!tp) + { tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(soap->tmpbuf)); + if (!tp) + return soap->error = SOAP_EOM; + strcpy(tp->name, soap->tmpbuf); + tp->value = NULL; + tp->size = 0; + /* if attribute name is qualified, append it to the end of the list */ + if (tq && strchr(soap->tmpbuf, ':')) + { tq->next = tp; + tp->next = NULL; + } + else + { tp->next = soap->attributes; + soap->attributes = tp; + } + } + while (soap_blank(c)) + c = soap_get1(soap); + if (c == '=') + { do c = soap_getutf8(soap); + while (soap_blank(c)); + if (c != SOAP_QT && c != SOAP_AP) + { soap_unget(soap, c); + c = ' '; /* blank delimiter */ + } + if (soap_getattrval(soap, tp->value, tp->size, c)) + { +#ifdef WITH_FAST + if (soap->error != SOAP_EOM) + return soap->error; + soap->error = SOAP_OK; + if (soap_store_lab(soap, tp->value, tp->size)) + return soap->error; + if (tp->value) + SOAP_FREE(soap, tp->value); + for (;;) + { if (soap_getattrval(soap, soap->labbuf + soap->labidx, soap->lablen - soap->labidx, c)) + { if (soap->error != SOAP_EOM) + return soap->error; + soap->error = SOAP_OK; + soap->labidx = soap->lablen; + if (soap_append_lab(soap, NULL, 0)) + return soap->error; + } + else + break; + } + if (soap->labidx) + tp->size = soap->lablen; + else + { tp->size = strlen(soap->labbuf) + 1; + if (tp->size < SOAP_LABLEN) + tp->size = SOAP_LABLEN; + } + if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size))) + return soap->error = SOAP_EOM; + strcpy(tp->value, soap->labbuf); +#else + size_t n; + if (soap->error != SOAP_EOM) + return soap->error; + soap->error = SOAP_OK; + if (soap_new_block(soap)) + return soap->error; + for (;;) + { if (!(s = (char*)soap_push_block(soap, SOAP_BLKLEN))) + return soap->error; + if (soap_getattrval(soap, s, SOAP_BLKLEN, c)) + { if (soap->error != SOAP_EOM) + return soap->error; + soap->error = SOAP_OK; + } + else + break; + } + n = tp->size + soap->blist->size; + if (!(s = (char*)SOAP_MALLOC(soap, n))) + return soap->error = SOAP_EOM; + if (tp->value) + { memcpy(s, tp->value, tp->size); + SOAP_FREE(soap, tp->value); + } + soap_save_block(soap, s + tp->size, 0); + tp->value = s; + tp->size = n; +#endif + } + do c = soap_get1(soap); + while (soap_blank(c)); + tp->visible = 2; /* seen this attribute w/ value */ +#ifdef WITH_DOM + if (att) + (*att)->data = soap_strdup(soap, tp->value); +#endif + } + else + tp->visible = 1; /* seen this attribute w/o value */ +#ifdef WITH_DOM + if (att) + att = &(*att)->next; +#endif + if (t && tp->value) + { if (soap_push_namespace(soap, t, tp->value)) + return soap->error; + } + } +#ifdef WITH_DOM + if (att) + { soap->dom->nstr = soap_current_namespace(soap, soap->tag); + for (att = &soap->dom->atts; *att; att = &(*att)->next) + (*att)->nstr = soap_current_namespace(soap, (*att)->name); + } +#endif + if ((int)c == EOF) + return soap->error = SOAP_EOF; + if (!(soap->body = (c != '/'))) + do c = soap_get1(soap); + while (soap_blank(c)); +#ifdef WITH_DOM + if (soap->mode & SOAP_XML_DOM) + { if (!soap->body && soap->dom->prnt) + soap->dom = soap->dom->prnt; + } +#endif + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible && tp->value) + { +#ifndef WITH_NOIDREF + if (!strcmp(tp->name, "id")) + { if ((soap->version > 0 && !(soap->mode & SOAP_XML_TREE)) + || (soap->mode & SOAP_XML_GRAPH)) + { *soap->id = '#'; + strncpy(soap->id + 1, tp->value, sizeof(soap->id) - 2); + soap->id[sizeof(soap->id)-1] = '\0'; + } + } + else if (!strcmp(tp->name, "href")) + { if (soap->version == 1 + || (soap->mode & SOAP_XML_GRAPH) + || (soap->mode & SOAP_ENC_MTOM)) + { strncpy(soap->href, tp->value, sizeof(soap->href) - 1); + soap->href[sizeof(soap->href)-1] = '\0'; + } + } + else +#endif + if (!soap_match_tag(soap, tp->name, "xsi:type")) + { strncpy(soap->type, tp->value, sizeof(soap->type) - 1); + soap->type[sizeof(soap->type)-1] = '\0'; + } + else if ((!soap_match_tag(soap, tp->name, "xsi:null") + || !soap_match_tag(soap, tp->name, "xsi:nil")) + && (!strcmp(tp->value, "1") + || !strcmp(tp->value, "true"))) + { soap->null = 1; + } + else if (soap->version == 1) + { if (!soap_match_tag(soap, tp->name, "SOAP-ENC:arrayType")) + { s = soap_strrchr(tp->value, '['); + if (s && (size_t)(s - tp->value) < sizeof(soap->arrayType)) + { strncpy(soap->arrayType, tp->value, s - tp->value); + soap->arrayType[s - tp->value] = '\0'; + strncpy(soap->arraySize, s, sizeof(soap->arraySize) - 1); + } + else + strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1); + soap->arraySize[sizeof(soap->arrayType)-1] = '\0'; + soap->arrayType[sizeof(soap->arrayType)-1] = '\0'; + } + else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:offset")) + strncpy(soap->arrayOffset, tp->value, sizeof(soap->arrayOffset)); + else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:position")) + soap->position = soap_getposition(tp->value, soap->positions); + else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:root")) + soap->root = ((!strcmp(tp->value, "1") || !strcmp(tp->value, "true"))); + else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand") + && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true"))) + soap->mustUnderstand = 1; + else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:actor")) + { if ((!soap->actor || strcmp(soap->actor, tp->value)) + && strcmp(tp->value, "http://schemas.xmlsoap.org/soap/actor/next")) + soap->other = 1; + } + } + else if (soap->version == 2) + { +#ifndef WITH_NOIDREF + if (!strcmp(tp->name, "ref") + || !soap_match_tag(soap, tp->name, "SOAP-ENC:ref")) + { *soap->href = '#'; + strncpy(soap->href + 1, tp->value, sizeof(soap->href) - 2); + soap->href[sizeof(soap->href)-1] = '\0'; + } + else +#endif + if (!soap_match_tag(soap, tp->name, "SOAP-ENC:itemType")) + strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1); + else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:arraySize")) + strncpy(soap->arraySize, tp->value, sizeof(soap->arraySize) - 1); + else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand") + && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true"))) + soap->mustUnderstand = 1; + else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:role")) + { if ((!soap->actor || strcmp(soap->actor, tp->value)) + && strcmp(tp->value, "http://www.w3.org/2003/05/soap-envelope/role/next")) + soap->other = 1; + } + } + } + } + return soap->error = SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_retry(struct soap *soap) +{ soap->error = SOAP_OK; + soap_revert(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_revert(struct soap *soap) +{ if (!soap->peeked) + { soap->peeked = 1; + if (soap->body) + soap->level--; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reverting last element (level=%u)\n", soap->level)); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_string_out(struct soap *soap, const char *s, int flag) +{ register const char *t; + register soap_wchar c; + register soap_wchar mask = 0xFFFFFF80UL; +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { soap->dom->data = soap_strdup(soap, s); + return SOAP_OK; + } +#endif + if (soap->mode & SOAP_C_UTFSTRING) + mask = 0; + t = s; + while ((c = *t++)) + { switch (c) + { + case 0x09: + if (flag) + { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, " ", 5)) + return soap->error; + s = t; + } + break; + case 0x0A: + if (flag || !(soap->mode & SOAP_XML_CANONICAL)) + { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, " ", 5)) + return soap->error; + s = t; + } + break; + case 0x0D: + if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, " ", 5)) + return soap->error; + s = t; + break; + case '&': + if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&", 5)) + return soap->error; + s = t; + break; + case '<': + if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "<", 4)) + return soap->error; + s = t; + break; + case '>': + if (!flag) + { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, ">", 4)) + return soap->error; + s = t; + } + break; + case '"': + if (flag) + { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, """, 6)) + return soap->error; + s = t; + } + break; + default: +#ifndef WITH_LEANER +#ifdef HAVE_MBTOWC + if (soap->mode & SOAP_C_MBSTRING) + { wchar_t wc; + register int m = mbtowc(&wc, t - 1, MB_CUR_MAX); + if (m > 0 && wc != c) + { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, wc)) + return soap->error; + s = t += m - 1; + continue; + } + } +#endif +#endif +#ifndef WITH_NOSTRINGTOUTF8 + if ((c & mask) || !(c & 0xFFFFFFE0UL)) + { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned char)c)) + return soap->error; + s = t; + } +#endif + } + } + return soap_send_raw(soap, s, t - s - 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_string_in(struct soap *soap, int flag, long minlen, long maxlen) +{ register char *s; + char *t = NULL; + register size_t i; + register long l = 0; + register int n = 0; + register int m = 0; + register soap_wchar c; +#if !defined(WITH_LEANER) && defined(HAVE_WCTOMB) + char buf[MB_LEN_MAX > 8 ? MB_LEN_MAX : 8]; +#else + char buf[8]; +#endif + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading string content\n")); + if (soap->peeked) + { if (!soap->body) + return NULL; + if (*soap->tag) + { +#ifndef WITH_LEAN + struct soap_attribute *tp; + t = soap->tmpbuf; + *t = '<'; + t[sizeof(soap->tmpbuf)-1] = '\0'; + strncpy(t + 1, soap->tag, sizeof(soap->tmpbuf) - 2); + t += strlen(t); + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible) + { if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2) + break; + *t++ = ' '; + strcpy(t, tp->name); + t += strlen(t); + if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2) + break; + if (tp->value) + { *t++ = '='; + *t++ = '"'; + strcpy(t, tp->value); + t += strlen(t); + *t++ = '"'; + } + } + } + *t++ = '>'; + *t = '\0'; + t = soap->tmpbuf; + m = (int)strlen(soap->tmpbuf); +#endif + n = 1; + soap->peeked = 0; + } + } +#ifdef WITH_CDATA + if (!flag) + { register int state = 0; +#ifdef WITH_FAST + soap->labidx = 0; /* use look-aside buffer */ +#else + if (soap_new_block(soap)) + return NULL; +#endif + for (;;) + { +#ifdef WITH_FAST + register size_t k; + if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */ + return NULL; + s = soap->labbuf + soap->labidx; /* space to populate */ + k = soap->lablen - soap->labidx; /* number of bytes available */ + soap->labidx = soap->lablen; /* claim this space */ +#else + register size_t k = SOAP_BLKLEN; + if (!(s = (char*)soap_push_block(soap, k))) + return NULL; +#endif + for (i = 0; i < k; i++) + { if (m > 0) + { *s++ = *t++; /* copy multibyte characters */ + m--; + continue; + } + c = soap_getchar(soap); + if ((int)c == EOF) + goto end; + if (c >= 0x80 && state != 1 && !(soap->mode & SOAP_ENC_LATIN)) + { soap_unget(soap, c); + c = soap_getutf8(soap); + if (soap->mode & SOAP_C_UTFSTRING) + { if ((c & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP) + { c &= 0x7FFFFFFF; + t = buf; + if (c < 0x0800) + *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); + else + { if (c < 0x010000) + *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + else + { if (c < 0x200000) + *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + else + { if (c < 0x04000000) + *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + else + { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + } + *t++ = (char)(0x80 | (c & 0x3F)); + m = (int)(t - buf) - 1; + t = buf; + *s++ = *t++; + continue; + } + } + } + switch (state) + { case 1: + if (c == ']') + state = 4; + *s++ = c; + continue; + case 2: + if (c == '-') + state = 6; + *s++ = c; + continue; + case 3: + if (c == '?') + state = 8; + *s++ = c; + continue; + /* CDATA */ + case 4: + if (c == ']') + state = 5; + else + state = 1; + *s++ = c; + continue; + case 5: + if (c == '>') + state = 0; + else + state = 1; + *s++ = c; + continue; + /* comment */ + case 6: + if (c == '-') + state = 7; + else + state = 2; + *s++ = c; + continue; + case 7: + if (c == '>') + state = 0; + else + state = 2; + *s++ = c; + continue; + /* PI */ + case 8: + if (c == '>') + state = 0; + else + state = 3; + *s++ = c; + continue; + } + switch (c) + { + case '/': + if (n > 0) + { c = soap_getchar(soap); + if (c == '>') + n--; + soap_unget(soap, c); + } + *s++ = '/'; + break; + case '<': + c = soap_getchar(soap); + if (c == '/') + { if (n == 0) + { c = SOAP_TT; + goto end; + } + n--; + } + else if (c == '!') + { c = soap_getchar(soap); + if (c == '[') + { do c = soap_getchar(soap); + while ((int)c != EOF && c != '['); + if ((int)c == EOF) + goto end; + t = (char*)"![CDATA["; + m = 8; + state = 1; + } + else if (c == '-') + { if ((c = soap_getchar(soap)) == '-') + state = 2; + t = (char*)"!-"; + m = 2; + soap_unget(soap, c); + } + else + { t = (char*)"!"; + m = 1; + soap_unget(soap, c); + } + *s++ = '<'; + break; + } + else if (c == '?') + state = 3; + else + n++; + soap_unget(soap, c); + *s++ = '<'; + break; + case '>': + *s++ = '>'; + break; + case '"': + *s++ = '"'; + break; + default: +#ifndef WITH_LEANER +#ifdef HAVE_WCTOMB + if (soap->mode & SOAP_C_MBSTRING) + { m = wctomb(buf, c & 0x7FFFFFFF); + if (m >= 1 && m <= (int)MB_CUR_MAX) + { t = buf; + *s++ = *t++; + m--; + } + else + { *s++ = SOAP_UNKNOWN_CHAR; + m = 0; + } + } + else +#endif +#endif + *s++ = (char)(c & 0xFF); + } + l++; + if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); + soap->error = SOAP_LENGTH; + return NULL; + } + } + } + } +#endif +#ifdef WITH_FAST + soap->labidx = 0; /* use look-aside buffer */ +#else + if (soap_new_block(soap)) + return NULL; +#endif + for (;;) + { +#ifdef WITH_FAST + register size_t k; + if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */ + return NULL; + s = soap->labbuf + soap->labidx; /* space to populate */ + k = soap->lablen - soap->labidx; /* number of bytes available */ + soap->labidx = soap->lablen; /* claim this space */ +#else + register size_t k = SOAP_BLKLEN; + if (!(s = (char*)soap_push_block(soap, k))) + return NULL; +#endif + for (i = 0; i < k; i++) + { if (m > 0) + { *s++ = *t++; /* copy multibyte characters */ + m--; + continue; + } + if (soap->mode & SOAP_C_UTFSTRING) + { if (((c = soap_get(soap)) & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP) + { c &= 0x7FFFFFFF; + t = buf; + if (c < 0x0800) + *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); + else + { if (c < 0x010000) + *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + else + { if (c < 0x200000) + *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + else + { if (c < 0x04000000) + *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + else + { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + } + *t++ = (char)(0x80 | (c & 0x3F)); + m = (int)(t - buf) - 1; + t = buf; + *s++ = *t++; + continue; + } + } + else + c = soap_getutf8(soap); + switch (c) + { + case SOAP_TT: + if (n == 0) + goto end; + n--; + *s++ = '<'; + t = (char*)"/"; + m = 1; + break; + case SOAP_LT: + n++; + *s++ = '<'; + break; + case SOAP_GT: + *s++ = '>'; + break; + case SOAP_QT: + *s++ = '"'; + break; + case SOAP_AP: + *s++ = '\''; + break; + case '/': + if (n > 0) + { c = soap_get(soap); + if (c == SOAP_GT) + n--; + soap_unget(soap, c); + } + *s++ = '/'; + break; + case (soap_wchar)('<' | 0x80000000): + if (flag) + *s++ = '<'; + else + { *s++ = '&'; + t = (char*)"lt;"; + m = 3; + } + break; + case (soap_wchar)('>' | 0x80000000): + if (flag) + *s++ = '>'; + else + { *s++ = '&'; + t = (char*)"gt;"; + m = 3; + } + break; + case (soap_wchar)('&' | 0x80000000): + if (flag) + *s++ = '&'; + else + { *s++ = '&'; + t = (char*)"amp;"; + m = 4; + } + break; + case (soap_wchar)('"' | 0x80000000): + if (flag) + *s++ = '"'; + else + { *s++ = '&'; + t = (char*)"quot;"; + m = 5; + } + break; + case (soap_wchar)('\'' | 0x80000000): + if (flag) + *s++ = '\''; + else + { *s++ = '&'; + t = (char*)"apos;"; + m = 5; + } + break; + default: + if ((int)c == EOF) + goto end; +#ifndef WITH_LEANER +#ifdef HAVE_WCTOMB + if (soap->mode & SOAP_C_MBSTRING) + { m = wctomb(buf, c & 0x7FFFFFFF); + if (m >= 1 && m <= (int)MB_CUR_MAX) + { t = buf; + *s++ = *t++; + m--; + } + else + { *s++ = SOAP_UNKNOWN_CHAR; + m = 0; + } + } + else +#endif +#endif + *s++ = (char)(c & 0xFF); + } + l++; + if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); + soap->error = SOAP_LENGTH; + return NULL; + } + } + } +end: + soap_unget(soap, c); + *s = '\0'; +#ifdef WITH_FAST + t = soap_strdup(soap, soap->labbuf); +#else + soap_size_block(soap, i+1); + t = soap_save_block(soap, NULL, 0); +#endif + if ((soap->mode & SOAP_XML_STRICT) && l < minlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen)); + soap->error = SOAP_LENGTH; + return NULL; + } +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { if (flag == 3) + soap->dom->tail = t; + else + soap->dom->data = t; + } +#endif + if (flag == 2) + if (soap_s2QName(soap, t, &t)) + return NULL; + return t; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_wstring_out(struct soap *soap, const wchar_t *s, int flag) +{ const char *t; + char tmp; + register soap_wchar c; +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { wchar_t *r = (wchar_t*)s; + int n = 1; + while (*r++) + n++; + soap->dom->wide = r = (wchar_t*)soap_malloc(soap, n * sizeof(wchar_t)); + while (n--) + *r++ = *s++; + return SOAP_OK; + } +#endif + while ((c = *s++)) + { switch (c) + { + case 0x09: + if (flag) + t = " "; + else + t = "\t"; + break; + case 0x0A: + if (flag || !(soap->mode & SOAP_XML_CANONICAL)) + t = " "; + else + t = "\n"; + break; + case 0x0D: + t = " "; + break; + case '&': + t = "&"; + break; + case '<': + t = "<"; + break; + case '>': + if (flag) + t = ">"; + else + t = ">"; + break; + case '"': + if (flag) + t = """; + else + t = "\""; + break; + default: + if (c >= 0x20 && c < 0x80) + { tmp = (char)c; + if (soap_send_raw(soap, &tmp, 1)) + return soap->error; + } + else if (soap_pututf8(soap, (unsigned long)c)) + return soap->error; + continue; + } + if (soap_send(soap, t)) + return soap->error; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +wchar_t * +SOAP_FMAC2 +soap_wstring_in(struct soap *soap, int flag, long minlen, long maxlen) +{ wchar_t *s; + register int i, n = 0; + register long l = 0; + register soap_wchar c; + char *t = NULL; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading wide string content\n")); + if (soap->peeked) + { if (!soap->body) + return NULL; + if (*soap->tag) + { +#ifndef WITH_LEAN + struct soap_attribute *tp; + t = soap->tmpbuf; + *t = '<'; + t[sizeof(soap->tmpbuf)-1] = '\0'; + strncpy(t + 1, soap->tag, sizeof(soap->tmpbuf) - 2); + t += strlen(t); + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible) + { if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2) + break; + *t++ = ' '; + strcpy(t, tp->name); + t += strlen(t); + if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2) + break; + if (tp->value) + { *t++ = '='; + *t++ = '"'; + strcpy(t, tp->value); + t += strlen(t); + *t++ = '"'; + } + } + } + *t++ = '>'; + *t = '\0'; + t = soap->tmpbuf; +#endif + n = 1; + soap->peeked = 0; + } + } + if (soap_new_block(soap)) + return NULL; + for (;;) + { if (!(s = (wchar_t*)soap_push_block(soap, sizeof(wchar_t)*SOAP_BLKLEN))) + return NULL; + for (i = 0; i < SOAP_BLKLEN; i++) + { if (t) + { *s++ = (wchar_t)*t++; + if (!*t) + t = NULL; + continue; + } + c = soap_getutf8(soap); + switch (c) + { + case SOAP_TT: + if (n == 0) + goto end; + n--; + *s++ = '<'; + soap_unget(soap, '/'); + break; + case SOAP_LT: + n++; + *s++ = '<'; + break; + case SOAP_GT: + *s++ = '>'; + break; + case SOAP_QT: + *s++ = '"'; + break; + case SOAP_AP: + *s++ = '\''; + break; + case '/': + if (n > 0) + { c = soap_getutf8(soap); + if (c == SOAP_GT) + n--; + soap_unget(soap, c); + } + *s++ = '/'; + break; + case '<': + if (flag) + *s++ = (soap_wchar)'<'; + else + { *s++ = (soap_wchar)'&'; + t = "lt;"; + } + break; + case '>': + if (flag) + *s++ = (soap_wchar)'>'; + else + { *s++ = (soap_wchar)'&'; + t = "gt;"; + } + break; + case '"': + if (flag) + *s++ = (soap_wchar)'"'; + else + { *s++ = (soap_wchar)'&'; + t = "quot;"; + } + break; + default: + if ((int)c == EOF) + goto end; + *s++ = (wchar_t)c & 0x7FFFFFFF; + } + l++; + if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); + soap->error = SOAP_LENGTH; + return NULL; + } + } + } +end: + soap_unget(soap, c); + *s = '\0'; + soap_size_block(soap, sizeof(wchar_t) * (i + 1)); + if ((soap->mode & SOAP_XML_STRICT) && l < minlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen)); + soap->error = SOAP_LENGTH; + return NULL; + } + s = (wchar_t*)soap_save_block(soap, NULL, 0); +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + soap->dom->wide = s; +#endif + return s; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_int2s(struct soap *soap, int n) +{ return soap_long2s(soap, (long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outint(struct soap *soap, const char *tag, int id, const int *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_long2s(soap, (long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2int(struct soap *soap, const char *s, int *p) +{ if (s) + { char *r; +#ifndef WITH_NOIO +#ifndef WITH_LEAN + soap_reset_errno; +#endif +#endif + *p = (int)soap_strtol(s, &r, 10); + if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r +#ifndef WITH_NOIO +#ifndef WITH_LEAN + || soap_errno == SOAP_ERANGE +#endif +#endif + ) + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int * +SOAP_FMAC2 +soap_inint(struct soap *soap, const char *tag, int *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":int") + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (int*)soap_id_enter(soap, soap->id, p, t, sizeof(int), 0, NULL, NULL, NULL); + if (*soap->href) + p = (int*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(int), 0, NULL); + else if (p) + { if (soap_s2int(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_long2s(struct soap *soap, long n) +{ sprintf(soap->tmpbuf, "%ld", n); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outlong(struct soap *soap, const char *tag, int id, const long *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_long2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2long(struct soap *soap, const char *s, long *p) +{ if (s) + { char *r; +#ifndef WITH_NOIO +#ifndef WITH_LEAN + soap_reset_errno; +#endif +#endif + *p = soap_strtol(s, &r, 10); + if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r +#ifndef WITH_NOIO +#ifndef WITH_LEAN + || soap_errno == SOAP_ERANGE +#endif +#endif + ) + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +long * +SOAP_FMAC2 +soap_inlong(struct soap *soap, const char *tag, long *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":int") + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (long*)soap_id_enter(soap, soap->id, p, t, sizeof(long), 0, NULL, NULL, NULL); + if (*soap->href) + p = (long*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(long), 0, NULL); + else if (p) + { if (soap_s2long(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_LONG642s(struct soap *soap, LONG64 n) +{ sprintf(soap->tmpbuf, SOAP_LONG_FORMAT, n); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outLONG64(struct soap *soap, const char *tag, int id, const LONG64 *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_LONG642s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2LONG64(struct soap *soap, const char *s, LONG64 *p) +{ if (s) + { +#ifdef HAVE_STRTOLL + char *r; +#ifndef WITH_NOIO +#ifndef WITH_LEAN + soap_reset_errno; +#endif +#endif + *p = strtoll(s, &r, 10); + if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r +#ifndef WITH_NOIO +#ifndef WITH_LEAN + || soap_errno == SOAP_ERANGE +#endif +#endif + ) +#else +# ifdef HAVE_SSCANF + if (sscanf(s, SOAP_LONG_FORMAT, p) != 1) +# endif +#endif + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +LONG64 * +SOAP_FMAC2 +soap_inLONG64(struct soap *soap, const char *tag, LONG64 *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":integer") + && soap_match_tag(soap, soap->type, ":positiveInteger") + && soap_match_tag(soap, soap->type, ":negativeInteger") + && soap_match_tag(soap, soap->type, ":nonPositiveInteger") + && soap_match_tag(soap, soap->type, ":nonNegativeInteger") + && soap_match_tag(soap, soap->type, ":long") + && soap_match_tag(soap, soap->type, ":int") + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (LONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(LONG64), 0, NULL, NULL, NULL); + if (*soap->href) + p = (LONG64*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(LONG64), 0, NULL); + else if (p) + { if (soap_s2LONG64(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_byte2s(struct soap *soap, char n) +{ return soap_long2s(soap, (long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outbyte(struct soap *soap, const char *tag, int id, const char *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_long2s(soap, (long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2byte(struct soap *soap, const char *s, char *p) +{ if (s) + { long n; + char *r; + n = soap_strtol(s, &r, 10); + if (s == r || *r || n < -128 || n > 127) + soap->error = SOAP_TYPE; + *p = (char)n; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_inbyte(struct soap *soap, const char *tag, char *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (char*)soap_id_enter(soap, soap->id, p, t, sizeof(char), 0, NULL, NULL, NULL); + if (*soap->href) + p = (char*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(char), 0, NULL); + else if (p) + { if (soap_s2byte(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_short2s(struct soap *soap, short n) +{ return soap_long2s(soap, (long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outshort(struct soap *soap, const char *tag, int id, const short *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_long2s(soap, (long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2short(struct soap *soap, const char *s, short *p) +{ if (s) + { long n; + char *r; + n = soap_strtol(s, &r, 10); + if (s == r || *r || n < -32768 || n > 32767) + soap->error = SOAP_TYPE; + *p = (short)n; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +short * +SOAP_FMAC2 +soap_inshort(struct soap *soap, const char *tag, short *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (short*)soap_id_enter(soap, soap->id, p, t, sizeof(short), 0, NULL, NULL, NULL); + if (*soap->href) + p = (short*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(short), 0, NULL); + else if (p) + { if (soap_s2short(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_float2s(struct soap *soap, float n) +{ char *s; + if (soap_isnan((double)n)) + return "NaN"; + if (soap_ispinff(n)) + return "INF"; + if (soap_isninff(n)) + return "-INF"; + s = soap->tmpbuf; +#if defined(HAVE_SPRINTF_L) + sprintf_l(s, NULL, soap->float_format, n); +#else + sprintf(s, soap->float_format, n); + s = strchr(s, ','); /* convert decimal comma to DP */ + if (s) + *s = '.'; +#endif + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outfloat(struct soap *soap, const char *tag, int id, const float *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_float2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2float(struct soap *soap, const char *s, float *p) +{ if (s) + { if (!*s) + return soap->error = SOAP_TYPE; + if (!soap_tag_cmp(s, "INF")) + *p = FLT_PINFTY; + else if (!soap_tag_cmp(s, "+INF")) + *p = FLT_PINFTY; + else if (!soap_tag_cmp(s, "-INF")) + *p = FLT_NINFTY; + else if (!soap_tag_cmp(s, "NaN")) + *p = FLT_NAN; + else + { +/* On some systems, strtof appears to be broken or doesn't link: use with caution */ +#if defined(HAVE_STRTOF_L) + char *r; + *p = strtof_l((char*)s, &r, NULL); + if (*r) +#elif defined(HAVE_STRTOD_L) + char *r; + *p = (float)strtod_l(s, &r, NULL); + if (*r) +#elif defined(HAVE_STRTOF) + char *r; + *p = strtof((char*)s, &r); + if (*r) +#elif defined(HAVE_STRTOD) + char *r; + *p = (float)strtod(s, &r); + if (*r) +#endif +#if defined(HAVE_SSCANF_L) + if (sscanf_l(s, NULL, "%g", p) != 1) + soap->error = SOAP_TYPE; +#elif defined(HAVE_SSCANF) + if (sscanf(s, "%g", p) != 1) + soap->error = SOAP_TYPE; +#else + soap->error = SOAP_TYPE; +#endif + } + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static int soap_isnumeric(struct soap *soap, const char *type) +{ if (soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":float") + && soap_match_tag(soap, soap->type, ":double") + && soap_match_tag(soap, soap->type, ":decimal") + && soap_match_tag(soap, soap->type, ":integer") + && soap_match_tag(soap, soap->type, ":positiveInteger") + && soap_match_tag(soap, soap->type, ":negativeInteger") + && soap_match_tag(soap, soap->type, ":nonPositiveInteger") + && soap_match_tag(soap, soap->type, ":nonNegativeInteger") + && soap_match_tag(soap, soap->type, ":long") + && soap_match_tag(soap, soap->type, ":int") + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte") + && soap_match_tag(soap, soap->type, ":unsignedLong") + && soap_match_tag(soap, soap->type, ":unsignedInt") + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return SOAP_ERR; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +float * +SOAP_FMAC2 +soap_infloat(struct soap *soap, const char *tag, float *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type != '\0' && soap_isnumeric(soap, type)) + return NULL; +#endif + p = (float*)soap_id_enter(soap, soap->id, p, t, sizeof(float), 0, NULL, NULL, NULL); + if (*soap->href) + p = (float*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(float), 0, NULL); + else if (p) + { if (soap_s2float(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_double2s(struct soap *soap, double n) +{ char *s; + if (soap_isnan(n)) + return "NaN"; + if (soap_ispinfd(n)) + return "INF"; + if (soap_isninfd(n)) + return "-INF"; + s = soap->tmpbuf; +#if defined(HAVE_SPRINTF_L) + sprintf_l(s, NULL, soap->double_format, n); +#else + sprintf(s, soap->double_format, n); + s = strchr(s, ','); /* convert decimal comma to DP */ + if (s) + *s = '.'; +#endif + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outdouble(struct soap *soap, const char *tag, int id, const double *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_double2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2double(struct soap *soap, const char *s, double *p) +{ if (s) + { if (!*s) + return soap->error = SOAP_TYPE; + if (!soap_tag_cmp(s, "INF")) + *p = DBL_PINFTY; + else if (!soap_tag_cmp(s, "+INF")) + *p = DBL_PINFTY; + else if (!soap_tag_cmp(s, "-INF")) + *p = DBL_NINFTY; + else if (!soap_tag_cmp(s, "NaN")) + *p = DBL_NAN; + else + { +#if defined(HAVE_STRTOD_L) + char *r; + *p = strtod_l(s, &r, NULL); + if (*r) +#elif defined(HAVE_STRTOD) + char *r; + *p = strtod(s, &r); + if (*r) +#endif +#if defined(HAVE_SSCANF_L) + if (sscanf_l(s, NULL, "%lg", p) != 1) + soap->error = SOAP_TYPE; +#elif defined(HAVE_SSCANF) + if (sscanf(s, "%lg", p) != 1) + soap->error = SOAP_TYPE; +#else + soap->error = SOAP_TYPE; +#endif + } + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +double * +SOAP_FMAC2 +soap_indouble(struct soap *soap, const char *tag, double *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type != '\0' && soap_isnumeric(soap, type)) + return NULL; +#endif + p = (double*)soap_id_enter(soap, soap->id, p, t, sizeof(double), 0, NULL, NULL, NULL); + if (*soap->href) + p = (double*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(double), 0, NULL); + else if (p) + { if (soap_s2double(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_unsignedByte2s(struct soap *soap, unsigned char n) +{ return soap_unsignedLong2s(soap, (unsigned long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outunsignedByte(struct soap *soap, const char *tag, int id, const unsigned char *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2unsignedByte(struct soap *soap, const char *s, unsigned char *p) +{ if (s) + { unsigned long n; + char *r; + n = soap_strtoul(s, &r, 10); + if (s == r || *r || n > 255) + soap->error = SOAP_TYPE; + *p = (unsigned char)n; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +unsigned char * +SOAP_FMAC2 +soap_inunsignedByte(struct soap *soap, const char *tag, unsigned char *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (unsigned char*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned char), 0, NULL, NULL, NULL); + if (*soap->href) + p = (unsigned char*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned char), 0, NULL); + else if (p) + { if (soap_s2unsignedByte(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_unsignedShort2s(struct soap *soap, unsigned short n) +{ return soap_unsignedLong2s(soap, (unsigned long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outunsignedShort(struct soap *soap, const char *tag, int id, const unsigned short *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2unsignedShort(struct soap *soap, const char *s, unsigned short *p) +{ if (s) + { unsigned long n; + char *r; + n = soap_strtoul(s, &r, 10); + if (s == r || *r || n > 65535) + soap->error = SOAP_TYPE; + *p = (unsigned short)n; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +unsigned short * +SOAP_FMAC2 +soap_inunsignedShort(struct soap *soap, const char *tag, unsigned short *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (unsigned short*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned short), 0, NULL, NULL, NULL); + if (*soap->href) + p = (unsigned short*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned short), 0, NULL); + else if (p) + { if (soap_s2unsignedShort(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_unsignedInt2s(struct soap *soap, unsigned int n) +{ return soap_unsignedLong2s(soap, (unsigned long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outunsignedInt(struct soap *soap, const char *tag, int id, const unsigned int *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2unsignedInt(struct soap *soap, const char *s, unsigned int *p) +{ if (s) + { char *r; +#ifndef WITH_NOIO +#ifndef WITH_LEAN + soap_reset_errno; +#endif +#endif + *p = (unsigned int)soap_strtoul(s, &r, 10); + if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r +#ifndef WITH_NOIO +#ifndef WITH_LEAN + || soap_errno == SOAP_ERANGE +#endif +#endif + ) + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +unsigned int * +SOAP_FMAC2 +soap_inunsignedInt(struct soap *soap, const char *tag, unsigned int *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":unsignedInt") + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (unsigned int*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned int), 0, NULL, NULL, NULL); + if (*soap->href) + p = (unsigned int*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned int), 0, NULL); + else if (p) + { if (soap_s2unsignedInt(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_unsignedLong2s(struct soap *soap, unsigned long n) +{ sprintf(soap->tmpbuf, "%lu", n); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outunsignedLong(struct soap *soap, const char *tag, int id, const unsigned long *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_unsignedLong2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2unsignedLong(struct soap *soap, const char *s, unsigned long *p) +{ if (s) + { char *r; +#ifndef WITH_NOIO +#ifndef WITH_LEAN + soap_reset_errno; +#endif +#endif + *p = soap_strtoul(s, &r, 10); + if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r +#ifndef WITH_NOIO +#ifndef WITH_LEAN + || soap_errno == SOAP_ERANGE +#endif +#endif + ) + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +unsigned long * +SOAP_FMAC2 +soap_inunsignedLong(struct soap *soap, const char *tag, unsigned long *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":unsignedInt") + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (unsigned long*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned long), 0, NULL, NULL, NULL); + if (*soap->href) + p = (unsigned long*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned long), 0, NULL); + else if (p) + { if (soap_s2unsignedLong(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_ULONG642s(struct soap *soap, ULONG64 n) +{ sprintf(soap->tmpbuf, SOAP_ULONG_FORMAT, n); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outULONG64(struct soap *soap, const char *tag, int id, const ULONG64 *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_ULONG642s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2ULONG64(struct soap *soap, const char *s, ULONG64 *p) +{ if (s) + { +#ifdef HAVE_STRTOULL + char *r; +#ifndef WITH_NOIO +#ifndef WITH_LEAN + soap_reset_errno; +#endif +#endif + *p = strtoull(s, &r, 10); + if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r +#ifndef WITH_NOIO +#ifndef WITH_LEAN + || soap_errno == SOAP_ERANGE +#endif +#endif + ) +#else +#ifdef HAVE_SSCANF + if (sscanf(s, SOAP_ULONG_FORMAT, p) != 1) +#endif +#endif + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +ULONG64 * +SOAP_FMAC2 +soap_inULONG64(struct soap *soap, const char *tag, ULONG64 *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":positiveInteger") + && soap_match_tag(soap, soap->type, ":nonNegativeInteger") + && soap_match_tag(soap, soap->type, ":unsignedLong") + && soap_match_tag(soap, soap->type, ":unsignedInt") + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } + p = (ULONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(ULONG64), 0, NULL, NULL, NULL); + if (*soap->href) + p = (ULONG64*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(ULONG64), 0, NULL); + else if (p) + { if (soap_s2ULONG64(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2string(struct soap *soap, const char *s, char **t) +{ if (s) + { if (!(*t = soap_strdup(soap, s))) + return soap->error = SOAP_EOM; + if (!(soap->mode & (SOAP_ENC_LATIN | SOAP_C_UTFSTRING))) + { /* TODO: consider truncating UTF8 to ASCII for regular XML attribute strings? */ + } + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2QName(struct soap *soap, const char *s, char **t) +{ if (s) + { soap->labidx = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Normalized namespace(s) of QNames '%s'", s)); + /* convert (by prefix normalize prefix) all QNames in s */ + for (;;) + { size_t n; + struct soap_nlist *np; + register const char *p; + /* skip blanks */ + while (*s && soap_blank(*s)) + s++; + if (!*s) + break; + /* find next QName */ + n = 1; + while (s[n] && !soap_blank(s[n])) + n++; + np = soap->nlist; + /* if there is no namespace stack, or prefix is "xml" then copy string */ + if (!np || !strncmp(s, "xml:", 4)) + { soap_append_lab(soap, s, n); + } + else /* we normalize the QName by replacing its prefix */ + { p = strchr(s, ':'); + if (p) + { size_t k = p - s; + while (np && (strncmp(np->id, s, k) || np->id[k])) + np = np->next; + p++; + } + else + { while (np && *np->id) + np = np->next; + p = s; + } + /* replace prefix */ + if (np) + { if (np->index >= 0 && soap->local_namespaces) + { const char *q = soap->local_namespaces[np->index].id; + if (q) + soap_append_lab(soap, q, strlen(q)); + } + else if (np->ns) + { soap_append_lab(soap, "\"", 1); + soap_append_lab(soap, np->ns, strlen(np->ns)); + soap_append_lab(soap, "\"", 1); + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\nNamespace prefix of '%s' not defined (index=%d, URI=%s)\n", s, np->index, np->ns?np->ns:"")); + return soap->error = SOAP_NAMESPACE; + } + } + else /* no namespace: assume default "" namespace */ + { soap_append_lab(soap, "\"\"", 2); + } + soap_append_lab(soap, ":", 1); + soap_append_lab(soap, p, n - (p-s)); + } + /* advance to next and add spacing */ + s += n; + if (*s) + soap_append_lab(soap, " ", 1); + } + soap_append_lab(soap, SOAP_STR_EOS, 1); + *t = soap_strdup(soap, soap->labbuf); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, " into '%s'\n", *t)); + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_QName2s(struct soap *soap, const char *s) +{ const char *t = NULL; + if (s) + { soap->labidx = 0; + for (;;) + { size_t n; + /* skip blanks */ + while (*s && soap_blank(*s)) + s++; + if (!*s) + break; + /* find next QName */ + n = 1; + while (s[n] && !soap_blank(s[n])) + n++; + /* normal prefix: pass string as is */ + if (*s != '"') + { soap_append_lab(soap, s, n); +#ifndef WITH_LEAN + if ((soap->mode & SOAP_XML_CANONICAL)) + { const char *r = strchr(s, ':'); + if (r) + soap_utilize_ns(soap, s, r - s); + } +#endif + } + else /* URL-based string prefix */ + { const char *q; + s++; + q = strchr(s, '"'); + if (q) + { struct Namespace *p = soap->local_namespaces; + if (p) + { for (; p->id; p++) + { if (p->ns) + if (!soap_tag_cmp(s, p->ns)) + break; + if (p->in) + if (!soap_tag_cmp(s, p->in)) + break; + } + } + /* URL is in the namespace table? */ + if (p && p->id) + { soap_append_lab(soap, p->id, strlen(p->id)); + } + else /* not in namespace table: create xmlns binding */ + { char *r = soap_strdup(soap, s); + r[q-s] = '\0'; + sprintf(soap->tmpbuf, "xmlns:_%d", soap->idnum++); + soap_set_attr(soap, soap->tmpbuf, r); + soap_append_lab(soap, soap->tmpbuf + 6, strlen(soap->tmpbuf + 6)); + } + soap_append_lab(soap, q + 1, n - (q-s) - 1); + } + } + /* advance to next and add spacing */ + s += n; + if (*s) + soap_append_lab(soap, " ", 1); + } + soap_append_lab(soap, SOAP_STR_EOS, 1); + t = soap_strdup(soap, soap->labbuf); + } + return t; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2wchar(struct soap *soap, const char *s, wchar_t **t) +{ if (s) + { wchar_t *r; + *t = r = (wchar_t*)soap_malloc(soap, sizeof(wchar_t) * (strlen(s) + 1)); + if (!r) + return soap->error; + if (soap->mode & SOAP_ENC_LATIN) + { while (*s) + *r++ = (wchar_t)*s++; + } + else + { /* Convert UTF8 to wchar */ + while (*s) + { register soap_wchar c, c1, c2, c3, c4; + c = *s++; + if (c < 0x80) + *r++ = (wchar_t)c; + else + { c1 = (soap_wchar)*s++ & 0x3F; + if (c < 0xE0) + *r++ = (wchar_t)(((soap_wchar)(c & 0x1F) << 6) | c1); + else + { c2 = (soap_wchar)*s++ & 0x3F; + if (c < 0xF0) + *r++ = (wchar_t)(((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2); + else + { c3 = (soap_wchar)*s++ & 0x3F; + if (c < 0xF8) + *r++ = (wchar_t)(((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3); + else + { c4 = (soap_wchar)*s++ & 0x3F; + if (c < 0xFC) + *r++ = (wchar_t)(((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4); + else + *r++ = (wchar_t)(((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(*s++ & 0x3F)); + } + } + } + } + } + } + *r = L'\0'; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_wchar2s(struct soap *soap, const wchar_t *s) +{ register soap_wchar c; + register char *r, *t; + const wchar_t *q = s; + size_t n = 0; + while ((c = *q++)) + { if (c > 0 && c < 0x80) + n++; + else + n += 6; + } + r = t = (char*)soap_malloc(soap, n + 1); + if (r) + { /* Convert wchar to UTF8 */ + while ((c = *s++)) + { if (c > 0 && c < 0x80) + *t++ = (char)c; + else + { if (c < 0x0800) + *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); + else + { if (c < 0x010000) + *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + else + { if (c < 0x200000) + *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + else + { if (c < 0x04000000) + *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + else + { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + } + *t++ = (char)(0x80 | (c & 0x3F)); + } + } + *t = '\0'; + } + return r; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outstring(struct soap *soap, const char *tag, int id, char *const*p, const char *type, int n) +{ id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n); + if (id < 0) + return soap->error; + if (!**p && (soap->mode & SOAP_C_NILSTRING)) + return soap_element_null(soap, tag, id, type); + if (soap_element_begin_out(soap, tag, id, type) + || soap_string_out(soap, *p, 0) + || soap_element_end_out(soap, tag)) + return soap->error; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char ** +SOAP_FMAC2 +soap_instring(struct soap *soap, const char *tag, char **p, const char *type, int t, int flag, long minlen, long maxlen) +{ if (soap_element_begin_in(soap, tag, 1, NULL)) + { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG) + return NULL; + soap->error = SOAP_OK; + } + if (!p) + { if (!(p = (char**)soap_malloc(soap, sizeof(char*)))) + return NULL; + } + if (soap->body) + { *p = soap_string_in(soap, flag, minlen, maxlen); + if (!*p || !(char*)soap_id_enter(soap, soap->id, *p, t, sizeof(char*), 0, NULL, NULL, NULL)) + return NULL; + if (!**p && tag && *tag == '-') + { soap->error = SOAP_NO_TAG; + return NULL; + } + } + else if (tag && *tag == '-') + { soap->error = SOAP_NO_TAG; + return NULL; + } + else if (soap->null) + *p = NULL; + else + *p = soap_strdup(soap, SOAP_STR_EOS); + if (*soap->href) + p = (char**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(char**), 0); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outwstring(struct soap *soap, const char *tag, int id, wchar_t *const*p, const char *type, int n) +{ id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n); + if (id < 0) + return soap->error; + if (!**p && (soap->mode & SOAP_C_NILSTRING)) + return soap_element_null(soap, tag, id, type); + if (soap_element_begin_out(soap, tag, id, type) + || soap_wstring_out(soap, *p, 0) + || soap_element_end_out(soap, tag)) + return soap->error; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +wchar_t ** +SOAP_FMAC2 +soap_inwstring(struct soap *soap, const char *tag, wchar_t **p, const char *type, int t, long minlen, long maxlen) +{ if (soap_element_begin_in(soap, tag, 1, NULL)) + { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG) + return NULL; + soap->error = SOAP_OK; + } + if (!p) + { if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*)))) + return NULL; + } + if (soap->body) + { *p = soap_wstring_in(soap, 1, minlen, maxlen); + if (!*p || !(wchar_t*)soap_id_enter(soap, soap->id, *p, t, sizeof(wchar_t*), 0, NULL, NULL, NULL)) + return NULL; + if (!**p && tag && *tag == '-') + { soap->error = SOAP_NO_TAG; + return NULL; + } + } + else if (tag && *tag == '-') + { soap->error = SOAP_NO_TAG; + return NULL; + } + else if (soap->null) + *p = NULL; + else + *p = soap_wstrdup(soap, (wchar_t*)SOAP_STR_EOS); + if (*soap->href) + p = (wchar_t**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(wchar_t**), 0); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +time_t +SOAP_FMAC2 +soap_timegm(struct tm *T) +{ +#if defined(HAVE_TIMEGM) + return timegm(T); +#else + time_t t, g, z; + struct tm tm; + t = mktime(T); + if (t == (time_t)-1) + return (time_t)-1; +#ifdef HAVE_GMTIME_R + gmtime_r(&t, &tm); +#else + tm = *gmtime(&t); +#endif + tm.tm_isdst = 0; + g = mktime(&tm); + if (g == (time_t)-1) + return (time_t)-1; + z = g - t; + return t - z; +#endif +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_dateTime2s(struct soap *soap, time_t n) +{ struct tm T, *pT = &T; +#if defined(HAVE_GMTIME_R) + if (gmtime_r(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); +#elif defined(HAVE_GMTIME) + if ((pT = gmtime(&n))) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); +#elif defined(HAVE_GETTIMEOFDAY) + struct timezone tz; + memset((void*)&tz, 0, sizeof(tz)); +#if defined(HAVE_LOCALTIME_R) + if (localtime_r(&n, pT)) + { struct timeval tv; + gettimeofday(&tv, &tz); + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60); + } +#else + if ((pT = localtime(&n))) + { struct timeval tv; + gettimeofday(&tv, &tz); + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60); + } +#endif +#elif defined(HAVE_FTIME) + struct timeb t; + memset((void*)&t, 0, sizeof(t)); +#if defined(HAVE_LOCALTIME_R) + if (localtime_r(&n, pT)) + { +#ifdef __BORLANDC__ + ::ftime(&t); +#else + ftime(&t); +#endif + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60); + } +#else + if ((pT = localtime(&n))) + { +#ifdef __BORLANDC__ + ::ftime(&t); +#else + ftime(&t); +#endif + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60); + } +#endif +#elif defined(HAVE_LOCALTIME_R) + if (localtime_r(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); +#else + if ((pT = localtime(&n))) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); +#endif + else + strcpy(soap->tmpbuf, "1969-12-31T23:59:59Z"); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outdateTime(struct soap *soap, const char *tag, int id, const time_t *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_dateTime2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2dateTime(struct soap *soap, const char *s, time_t *p) +{ if (s) + { struct tm T; + char zone[32]; + const char *t; + memset((void*)&T, 0, sizeof(T)); + zone[sizeof(zone)-1] = '\0'; + if (strchr(s, '-')) + t = "%d-%d-%dT%d:%d:%d%31s"; + else if (strchr(s, ':')) + t = "%4d%2d%2dT%d:%d:%d%31s"; + else /* parse non-XSD-standard alternative ISO 8601 format */ + t = "%4d%2d%2dT%2d%2d%2d%31s"; + sscanf(s, t, &T.tm_year, &T.tm_mon, &T.tm_mday, &T.tm_hour, &T.tm_min, &T.tm_sec, zone); + if (T.tm_year == 1) + T.tm_year = 70; + else + T.tm_year -= 1900; + T.tm_mon--; + if (*zone) + { if (*zone == '.') + { for (s = zone + 1; *s; s++) + if (*s < '0' || *s > '9') + break; + } + else + s = zone; + if (*s == '+' || *s == '-') + { int h = 0, m = 0; + if (s[3] == ':') + { sscanf(s, "%d:%d", &h, &m); + if (h < 0) + m = -m; + } + else + { m = (int)atol(s); + h = m / 100; + m = m % 100; + } + T.tm_hour -= h; + T.tm_min -= m; + } + T.tm_isdst = 0; + *p = soap_timegm(&T); + } + else + { T.tm_isdst = -1; + *p = mktime(&T); /* no time zone: suppose it is localtime? */ + } + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +time_t * +SOAP_FMAC2 +soap_indateTime(struct soap *soap, const char *tag, time_t *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":dateTime")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } + p = (time_t*)soap_id_enter(soap, soap->id, p, t, sizeof(time_t), 0, NULL, NULL, NULL); + if (*soap->href) + p = (time_t*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(time_t), 0, NULL); + else if (p) + { if (soap_s2dateTime(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outliteral(struct soap *soap, const char *tag, char *const*p, const char *type) +{ int i; + const char *t = NULL; + if (tag && *tag != '-') + { if (soap->local_namespaces && (t = strchr(tag, ':'))) + { strncpy(soap->tmpbuf, tag, t-tag); + soap->tmpbuf[t-tag] = '\0'; + for (i = 0; soap->local_namespaces[i].id; i++) + if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id)) + break; + t++; + if (soap_element(soap, t, 0, type) + || soap_attribute(soap, "xmlns", soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS) + || soap_element_start_end_out(soap, NULL)) + return soap->error; + } + else + { t = tag; + if (soap_element_begin_out(soap, t, 0, type)) + return soap->error; + } + } + if (p && *p) + { if (soap_send(soap, *p)) + return soap->error; + } + if (t) + return soap_element_end_out(soap, t); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char ** +SOAP_FMAC2 +soap_inliteral(struct soap *soap, const char *tag, char **p) +{ if (soap_element_begin_in(soap, tag, 1, NULL)) + { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT) + return NULL; + soap->error = SOAP_OK; + } + if (!p) + { if (!(p = (char**)soap_malloc(soap, sizeof(char*)))) + return NULL; + } + if (soap->body) + { *p = soap_string_in(soap, 0, -1, -1); + if (!*p) + return NULL; + if (!**p && tag && *tag == '-') + { soap->error = SOAP_NO_TAG; + return NULL; + } + } + else if (tag && *tag == '-') + { soap->error = SOAP_NO_TAG; + return NULL; + } + else if (soap->null) + *p = NULL; + else + *p = soap_strdup(soap, SOAP_STR_EOS); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outwliteral(struct soap *soap, const char *tag, wchar_t *const*p, const char *type) +{ int i; + const char *t = NULL; + if (tag && *tag != '-') + { if (soap->local_namespaces && (t = strchr(tag, ':'))) + { strncpy(soap->tmpbuf, tag, t-tag); + soap->tmpbuf[t-tag] = '\0'; + for (i = 0; soap->local_namespaces[i].id; i++) + if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id)) + break; + t++; + if (soap_element(soap, t, 0, type) + || soap_attribute(soap, "xmlns", soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS) + || soap_element_start_end_out(soap, NULL)) + return soap->error; + } + else + { t = tag; + if (soap_element_begin_out(soap, t, 0, type)) + return soap->error; + } + if (soap_send(soap, soap->tmpbuf)) + return soap->error; + } + if (p) + { wchar_t c; + const wchar_t *s = *p; + while ((c = *s++)) + { if (soap_pututf8(soap, (unsigned long)c)) + return soap->error; + } + } + if (t) + return soap_element_end_out(soap, t); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +wchar_t ** +SOAP_FMAC2 +soap_inwliteral(struct soap *soap, const char *tag, wchar_t **p) +{ if (soap_element_begin_in(soap, tag, 1, NULL)) + { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT) + return NULL; + soap->error = SOAP_OK; + } + if (!p) + { if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*)))) + return NULL; + } + if (soap->body) + { *p = soap_wstring_in(soap, 0, -1, -1); + if (!*p) + return NULL; + if (!**p && tag && *tag == '-') + { soap->error = SOAP_NO_TAG; + return NULL; + } + } + else if (tag && *tag == '-') + { soap->error = SOAP_NO_TAG; + return NULL; + } + else if (soap->null) + *p = NULL; + else + *p = soap_wstrdup(soap, (wchar_t*)SOAP_STR_EOS); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char * +SOAP_FMAC2 +soap_value(struct soap *soap) +{ register size_t i; + register soap_wchar c = 0; + register char *s = soap->tmpbuf; + if (!soap->body) + return SOAP_STR_EOS; + do c = soap_get(soap); + while (soap_blank(c)); + for (i = 0; i < sizeof(soap->tmpbuf) - 1; i++) + { if (c == SOAP_TT || (int)c == EOF) + break; + *s++ = (char)c; + c = soap_get(soap); + } + for (s--; i > 0; i--, s--) + { if (!soap_blank(*s)) + break; + } + s[1] = '\0'; + if ((int)c == EOF || c == SOAP_TT) + soap_unget(soap, c); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element content value='%s'\n", soap->tmpbuf)); +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + soap->dom->data = soap_strdup(soap, soap->tmpbuf); +#endif + return soap->tmpbuf; /* return non-null pointer */ +} +#endif + +/******************************************************************************/ +#if !defined(WITH_LEANER) || !defined(WITH_NOHTTP) +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getline(struct soap *soap, char *s, int len) +{ int i = len; + soap_wchar c = 0; + for (;;) + { while (--i > 0) + { c = soap_getchar(soap); + if (c == '\r' || c == '\n') + break; + if ((int)c == EOF) + return soap->error = SOAP_EOF; + *s++ = (char)c; + } + if (c != '\n') + c = soap_getchar(soap); /* got \r or something else, now get \n */ + if (c == '\n') + { *s = '\0'; + if (i+1 == len) /* empty line: end of HTTP/MIME header */ + break; + c = soap_get0(soap); + if (c != ' ' && c != '\t') /* HTTP line continuation? */ + break; + } + else if ((int)c == EOF) + return soap->error = SOAP_EOF; + } + if (i < 0) + return soap->error = SOAP_HDR; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static size_t +soap_count_attachments(struct soap *soap) +{ +#ifndef WITH_LEANER + register struct soap_multipart *content; + register size_t count = soap->count; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the message size with attachments, current count=%lu\n", (unsigned long)count)); + if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of DIME attachments\n")); + for (content = soap->dime.first; content; content = content->next) + { count += 12 + ((content->size+3)&(~3)); + if (content->id) + count += ((strlen(content->id)+3)&(~3)); + if (content->type) + count += ((strlen(content->type)+3)&(~3)); + if (content->options) + count += ((((unsigned char)content->options[2] << 8) | ((unsigned char)content->options[3]))+7)&(~3); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of DIME attachment content is %lu bytes\n", (unsigned long)content->size)); + } + } + if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary) + { register size_t n = strlen(soap->mime.boundary); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of MIME attachments\n")); + for (content = soap->mime.first; content; content = content->next) + { register const char *s; + /* count \r\n--boundary\r\n */ + count += 6 + n; + /* count Content-Type: ...\r\n */ + if (content->type) + count += 16 + strlen(content->type); + /* count Content-Transfer-Encoding: ...\r\n */ + s = soap_code_str(mime_codes, content->encoding); + if (s) + count += 29 + strlen(s); + /* count Content-ID: ...\r\n */ + if (content->id) + count += 14 + strlen(content->id); + /* count Content-Location: ...\r\n */ + if (content->location) + count += 20 + strlen(content->location); + /* count Content-Description: ...\r\n */ + if (content->description) + count += 23 + strlen(content->description); + /* count \r\n...content */ + count += 2 + content->size; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of MIME attachment content is %lu bytes\n", (unsigned long)content->size)); + } + /* count \r\n--boundary-- */ + count += 6 + n; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New count is %lu bytes\n", (unsigned long)count)); + return count; +#else + return soap->count; +#endif +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static int +soap_putdimefield(struct soap *soap, const char *s, size_t n) +{ if (soap_send_raw(soap, s, n)) + return soap->error; + return soap_send_raw(soap, SOAP_STR_PADDING, -(long)n&3); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_dime_option(struct soap *soap, unsigned short optype, const char *option) +{ size_t n; + char *s = NULL; + if (option) + { n = strlen(option); + s = (char*)soap_malloc(soap, n + 5); + if (s) + { s[0] = (char)(optype >> 8); + s[1] = (char)(optype & 0xFF); + s[2] = (char)(n >> 8); + s[3] = (char)(n & 0xFF); + strcpy(s + 4, option); + } + } + return s; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putdimehdr(struct soap *soap) +{ unsigned char tmp[12]; + size_t optlen = 0, idlen = 0, typelen = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Put DIME header id='%s'\n", soap->dime.id?soap->dime.id:"")); + if (soap->dime.options) + optlen = (((unsigned char)soap->dime.options[2] << 8) | ((unsigned char)soap->dime.options[3])) + 4; + if (soap->dime.id) + { idlen = strlen(soap->dime.id); + if (idlen > 0x0000FFFF) + idlen = 0x0000FFFF; + } + if (soap->dime.type) + { typelen = strlen(soap->dime.type); + if (typelen > 0x0000FFFF) + typelen = 0x0000FFFF; + } + tmp[0] = SOAP_DIME_VERSION | (soap->dime.flags & 0x7); + tmp[1] = soap->dime.flags & 0xF0; + tmp[2] = (char)(optlen >> 8); + tmp[3] = (char)(optlen & 0xFF); + tmp[4] = (char)(idlen >> 8); + tmp[5] = (char)(idlen & 0xFF); + tmp[6] = (char)(typelen >> 8); + tmp[7] = (char)(typelen & 0xFF); + tmp[8] = (char)(soap->dime.size >> 24); + tmp[9] = (char)((soap->dime.size >> 16) & 0xFF); + tmp[10] = (char)((soap->dime.size >> 8) & 0xFF); + tmp[11] = (char)(soap->dime.size & 0xFF); + if (soap_send_raw(soap, (char*)tmp, 12) + || soap_putdimefield(soap, soap->dime.options, optlen) + || soap_putdimefield(soap, soap->dime.id, idlen) + || soap_putdimefield(soap, soap->dime.type, typelen)) + return soap->error; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putdime(struct soap *soap) +{ struct soap_multipart *content; + if (!(soap->mode & SOAP_ENC_DIME)) + return SOAP_OK; + for (content = soap->dime.first; content; content = content->next) + { void *handle; + soap->dime.size = content->size; + soap->dime.id = content->id; + soap->dime.type = content->type; + soap->dime.options = content->options; + soap->dime.flags = SOAP_DIME_VERSION | SOAP_DIME_MEDIA; + if (soap->fdimereadopen && ((handle = soap->fdimereadopen(soap, (void*)content->ptr, content->id, content->type, content->options)) || soap->error)) + { size_t size = content->size; + if (!handle) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadopen failed\n")); + return soap->error; + } + if (!size && ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE)) + { size_t chunksize = sizeof(soap->tmpbuf); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming DIME\n")); + do + { size = soap->fdimeread(soap, handle, soap->tmpbuf, chunksize); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread returned %lu bytes\n", (unsigned long)size)); + if (size < chunksize) + { soap->dime.flags &= ~SOAP_DIME_CF; + if (!content->next) + soap->dime.flags |= SOAP_DIME_ME; + } + else + soap->dime.flags |= SOAP_DIME_CF; + soap->dime.size = size; + if (soap_putdimehdr(soap) + || soap_putdimefield(soap, soap->tmpbuf, size)) + break; + if (soap->dime.id) + { soap->dime.flags &= ~(SOAP_DIME_MB | SOAP_DIME_MEDIA); + soap->dime.id = NULL; + soap->dime.type = NULL; + soap->dime.options = NULL; + } + } while (size >= chunksize); + } + else + { if (!content->next) + soap->dime.flags |= SOAP_DIME_ME; + if (soap_putdimehdr(soap)) + return soap->error; + do + { size_t bufsize; + if (size < sizeof(soap->tmpbuf)) + bufsize = size; + else + bufsize = sizeof(soap->tmpbuf); + if (!(bufsize = soap->fdimeread(soap, handle, soap->tmpbuf, bufsize))) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size)); + soap->error = SOAP_EOF; + break; + } + if (soap_send_raw(soap, soap->tmpbuf, bufsize)) + break; + size -= bufsize; + } while (size); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n")); + soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3); + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n")); + if (soap->fdimereadclose) + soap->fdimereadclose(soap, handle); + } + else + { if (!content->next) + soap->dime.flags |= SOAP_DIME_ME; + if (soap_putdimehdr(soap) + || soap_putdimefield(soap, (char*)content->ptr, content->size)) + return soap->error; + } + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static char * +soap_getdimefield(struct soap *soap, size_t n) +{ register soap_wchar c; + register size_t i; + register char *s; + register char *p = NULL; + if (n) + { p = (char*)soap_malloc(soap, n + 1); + if (p) + { s = p; + for (i = n; i > 0; i--) + { if ((int)(c = soap_get1(soap)) == EOF) + { soap->error = SOAP_EOF; + return NULL; + } + *s++ = (char)c; + } + *s = '\0'; + if ((soap->error = soap_move(soap, -(long)n&3))) + return NULL; + } + else + soap->error = SOAP_EOM; + } + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getdimehdr(struct soap *soap) +{ register soap_wchar c; + register char *s; + register int i; + unsigned char tmp[12]; + size_t optlen, idlen, typelen; + if (!(soap->mode & SOAP_ENC_DIME)) + return soap->error = SOAP_DIME_END; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME header\n")); + if (soap->dime.buflen || soap->dime.chunksize) + { if (soap_move(soap, (long)(soap->dime.size - soap_tell(soap)))) + return soap->error = SOAP_EOF; + soap_unget(soap, soap_getchar(soap)); /* skip padding and get hdr */ + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... From chunked\n")); + return SOAP_OK; + } + s = (char*)tmp; + for (i = 12; i > 0; i--) + { if ((int)(c = soap_getchar(soap)) == EOF) + return soap->error = SOAP_EOF; + *s++ = (char)c; + } + if ((tmp[0] & 0xF8) != SOAP_DIME_VERSION) + return soap->error = SOAP_DIME_MISMATCH; + soap->dime.flags = (tmp[0] & 0x7) | (tmp[1] & 0xF0); + optlen = (tmp[2] << 8) | tmp[3]; + idlen = (tmp[4] << 8) | tmp[5]; + typelen = (tmp[6] << 8) | tmp[7]; + soap->dime.size = (tmp[8] << 24) | (tmp[9] << 16) | (tmp[10] << 8) | tmp[11]; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME size=%lu flags=0x%X\n", (unsigned long)soap->dime.size, soap->dime.flags)); + if (!(soap->dime.options = soap_getdimefield(soap, optlen)) && soap->error) + return soap->error; + if (!(soap->dime.id = soap_getdimefield(soap, idlen)) && soap->error) + return soap->error; + if (!(soap->dime.type = soap_getdimefield(soap, typelen)) && soap->error) + return soap->error; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME id=%s, type=%s, options=%s\n", soap->dime.id?soap->dime.id:"", soap->dime.type?soap->dime.type:"", soap->dime.options?soap->dime.options+4:"")); + if (soap->dime.flags & SOAP_DIME_ME) + soap->mode &= ~SOAP_ENC_DIME; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getdime(struct soap *soap) +{ while (soap->dime.flags & SOAP_DIME_CF) + { if (soap_getdimehdr(soap)) + return soap->error; + if (soap_move(soap, (long)soap->dime.size)) + return soap->error = SOAP_EOF; + } + if (soap_move(soap, (long)(((soap->dime.size+3)&(~3))-soap_tell(soap)))) + return soap->error = SOAP_EOF; + for (;;) + { register struct soap_multipart *content; + if (soap_getdimehdr(soap)) + break; + if (soap->fdimewriteopen && ((soap->dime.ptr = (char*)soap->fdimewriteopen(soap, soap->dime.id, soap->dime.type, soap->dime.options)) || soap->error)) + { const char *id, *type, *options; + size_t size, n; + if (!soap->dime.ptr) + return soap->error; + id = soap->dime.id; + type = soap->dime.type; + options = soap->dime.options; + for (;;) + { size = soap->dime.size; + for (;;) + { n = soap->buflen - soap->bufidx; + if (size < n) + n = size; + if ((soap->error = soap->fdimewrite(soap, (void*)soap->dime.ptr, soap->buf + soap->bufidx, n))) + break; + size -= n; + if (!size) + { soap->bufidx += n; + break; + } + if (soap_recv(soap)) + { soap->error = SOAP_EOF; + goto end; + } + } + if (soap_move(soap, -(long)soap->dime.size&3)) + { soap->error = SOAP_EOF; + break; + } + if (!(soap->dime.flags & SOAP_DIME_CF)) + break; + if (soap_getdimehdr(soap)) + break; + } +end: + if (soap->fdimewriteclose) + soap->fdimewriteclose(soap, (void*)soap->dime.ptr); + soap->dime.size = 0; + soap->dime.id = id; + soap->dime.type = type; + soap->dime.options = options; + } + else if (soap->dime.flags & SOAP_DIME_CF) + { const char *id, *type, *options; + id = soap->dime.id; + type = soap->dime.type; + options = soap->dime.options; + if (soap_new_block(soap)) + return SOAP_EOM; + for (;;) + { register soap_wchar c; + register size_t i; + register char *s; + s = (char*)soap_push_block(soap, soap->dime.size); + if (!s) + return soap->error = SOAP_EOM; + for (i = soap->dime.size; i > 0; i--) + { if ((int)(c = soap_get1(soap)) == EOF) + return soap->error = SOAP_EOF; + *s++ = (char)c; + } + if (soap_move(soap, -(long)soap->dime.size&3)) + return soap->error = SOAP_EOF; + if (!(soap->dime.flags & SOAP_DIME_CF)) + break; + if (soap_getdimehdr(soap)) + return soap->error; + } + soap->dime.size = soap->blist->size++; /* allocate one more for '\0' */ + if (!(soap->dime.ptr = soap_save_block(soap, NULL, 0))) + return soap->error; + soap->dime.ptr[soap->dime.size] = '\0'; /* force 0-terminated */ + soap->dime.id = id; + soap->dime.type = type; + soap->dime.options = options; + } + else + soap->dime.ptr = soap_getdimefield(soap, soap->dime.size); + content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, soap->dime.ptr, soap->dime.size); + if (!content) + return soap->error = SOAP_EOM; + content->id = soap->dime.id; + content->type = soap->dime.type; + content->options = soap->dime.options; + if (soap->error) + return soap->error; + soap_resolve_attachment(soap, content); + } + if (soap->error != SOAP_DIME_END) + return soap->error; + return soap->error = SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getmimehdr(struct soap *soap) +{ struct soap_multipart *content; + do + { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) + return soap->error; + } + while (!*soap->msgbuf); + if (soap->msgbuf[0] == '-' && soap->msgbuf[1] == '-') + { char *s = soap->msgbuf + strlen(soap->msgbuf) - 1; + /* remove white space */ + while (soap_blank(*s)) + s--; + s[1] = '\0'; + if (soap->mime.boundary) + { if (strcmp(soap->msgbuf + 2, soap->mime.boundary)) + return soap->error = SOAP_MIME_ERROR; + } + else + soap->mime.boundary = soap_strdup(soap, soap->msgbuf + 2); + if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) + return soap->error; + } + if (soap_set_mime_attachment(soap, NULL, 0, SOAP_MIME_NONE, NULL, NULL, NULL, NULL)) + return soap->error = SOAP_EOM; + content = soap->mime.last; + for (;;) + { register char *key = soap->msgbuf; + register char *val; + if (!*key) + break; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "MIME header: %s\n", key)); + val = strchr(soap->msgbuf, ':'); + if (val) + { *val = '\0'; + do val++; + while (*val && *val <= 32); + if (!soap_tag_cmp(key, "Content-ID")) + content->id = soap_strdup(soap, val); + else if (!soap_tag_cmp(key, "Content-Location")) + content->location = soap_strdup(soap, val); + else if (!soap_tag_cmp(key, "Content-Disposition")) + content->id = soap_strdup(soap, soap_get_header_attribute(soap, val, "name")); + else if (!soap_tag_cmp(key, "Content-Type")) + content->type = soap_strdup(soap, val); + else if (!soap_tag_cmp(key, "Content-Description")) + content->description = soap_strdup(soap, val); + else if (!soap_tag_cmp(key, "Content-Transfer-Encoding")) + content->encoding = (enum soap_mime_encoding)soap_code_int(mime_codes, val, (long)SOAP_MIME_NONE); + } + if (soap_getline(soap, key, sizeof(soap->msgbuf))) + return soap->error; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getmime(struct soap *soap) +{ while (soap_get_mime_attachment(soap, NULL)) + ; + return soap->error; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_post_check_mime_attachments(struct soap *soap) +{ soap->imode |= SOAP_MIME_POSTCHECK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_check_mime_attachments(struct soap *soap) +{ if (soap->mode & SOAP_MIME_POSTCHECK) + return soap_get_mime_attachment(soap, NULL) != NULL; + return 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +struct soap_multipart * +SOAP_FMAC2 +soap_get_mime_attachment(struct soap *soap, void *handle) +{ register soap_wchar c = 0; + register size_t i, m = 0; + register char *s, *t = NULL; + register struct soap_multipart *content; + register short flag = 0; + if (!(soap->mode & SOAP_ENC_MIME)) + return NULL; + content = soap->mime.last; + if (!content) + { if (soap_getmimehdr(soap)) + return NULL; + content = soap->mime.last; + } + else if (content != soap->mime.first) + { if (soap->fmimewriteopen && ((content->ptr = (char*)soap->fmimewriteopen(soap, (void*)handle, content->id, content->type, content->description, content->encoding)) || soap->error)) + { if (!content->ptr) + return NULL; + } + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Parsing MIME content id=%s type=%s\n", content->id?content->id:"", content->type?content->type:"")); + if (!content->ptr && soap_new_block(soap)) + { soap->error = SOAP_EOM; + return NULL; + } + for (;;) + { if (content->ptr) + s = soap->tmpbuf; + else if (!(s = (char*)soap_push_block(soap, sizeof(soap->tmpbuf)))) + { soap->error = SOAP_EOM; + return NULL; + } + for (i = 0; i < sizeof(soap->tmpbuf); i++) + { if (m > 0) + { *s++ = *t++; + m--; + } + else + { if (!flag) + { c = soap_get1(soap); + if ((int)c == EOF) + { soap->error = SOAP_EOF; + return NULL; + } + } + if (flag || c == '\r') + { t = soap->msgbuf; + memset(t, 0, sizeof(soap->msgbuf)); + strcpy(t, "\n--"); + if (soap->mime.boundary) + strncat(t, soap->mime.boundary, sizeof(soap->msgbuf)-4); + do c = soap_getchar(soap); + while (c == *t++); + if ((int)c == EOF) + { soap->error = SOAP_EOF; + return NULL; + } + if (!*--t) + goto end; + *t = (char)c; + flag = (c == '\r'); + m = t - soap->msgbuf + 1 - flag; + t = soap->msgbuf; + c = '\r'; + } + *s++ = (char)c; + } + } + if (content->ptr && soap->fmimewrite) + { if ((soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i))) + break; + } + } +end: + *s = '\0'; /* force 0-terminated */ + if (content->ptr) + { if (!soap->error && soap->fmimewrite) + soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i); + if (soap->fmimewriteclose) + soap->fmimewriteclose(soap, (void*)content->ptr); + if (soap->error) + return NULL; + } + else + { content->size = soap_size_block(soap, i+1)-1; + content->ptr = soap_save_block(soap, NULL, 0); + } + soap_resolve_attachment(soap, content); + if (c == '-' && soap_getchar(soap) == '-') + { soap->mode &= ~SOAP_ENC_MIME; + if ((soap->mode & SOAP_MIME_POSTCHECK) && soap_end_recv(soap)) + return NULL; + } + else + { while (c != '\r' && (int)c != EOF && soap_blank(c)) + c = soap_getchar(soap); + if (c != '\r' || soap_getchar(soap) != '\n') + { soap->error = SOAP_MIME_ERROR; + return NULL; + } + if (soap_getmimehdr(soap)) + return NULL; + } + return content; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_match_cid(struct soap *soap, const char *s, const char *t) +{ register size_t n; + if (!s) + return 1; + if (!strcmp(s, t)) + return 0; + if (!strncmp(s, "cid:", 4)) + s += 4; + n = strlen(t); + if (*t == '<') + { t++; + n -= 2; + } + if (!strncmp(s, t, n) && !s[n]) + return 0; + soap_decode(soap->tmpbuf, sizeof(soap->tmpbuf), s, SOAP_STR_EOS); + if (!strncmp(soap->tmpbuf, t, n) && !soap->tmpbuf[n]) + return 0; + return 1; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static void +soap_resolve_attachment(struct soap *soap, struct soap_multipart *content) +{ if (content->id) + { register struct soap_xlist **xp = &soap->xlist; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving attachment data for id=%s\n", content->id)); + while (*xp) + { register struct soap_xlist *xq = *xp; + if (!soap_match_cid(soap, xq->id, content->id)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Found matching attachment %s for content id=%s\n", xq->id, content->id)); + *xp = xq->next; + *xq->ptr = (unsigned char*)content->ptr; + *xq->size = (int)content->size; + *xq->type = (char*)content->type; + if (content->options) + *xq->options = (char*)content->options; + else + *xq->options = (char*)content->description; + SOAP_FREE(soap, xq); + } + else + xp = &(*xp)->next; + } + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putmimehdr(struct soap *soap, struct soap_multipart *content) +{ const char *s; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "MIME attachment type=%s\n", content->type?content->type:"")); + if (soap_send3(soap, "\r\n--", soap->mime.boundary, "\r\n")) + return soap->error; + if (content->type && soap_send3(soap, "Content-Type: ", content->type, "\r\n")) + return soap->error; + s = soap_code_str(mime_codes, content->encoding); + if (s && soap_send3(soap, "Content-Transfer-Encoding: ", s, "\r\n")) + return soap->error; + if (content->id && soap_send3(soap, "Content-ID: ", content->id, "\r\n")) + return soap->error; + if (content->location && soap_send3(soap, "Content-Location: ", content->location, "\r\n")) + return soap->error; + if (content->description && soap_send3(soap, "Content-Description: ", content->description, "\r\n")) + return soap->error; + return soap_send_raw(soap, "\r\n", 2); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putmime(struct soap *soap) +{ struct soap_multipart *content; + if (!(soap->mode & SOAP_ENC_MIME) || !soap->mime.boundary) + return SOAP_OK; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending MIME attachments\n")); + for (content = soap->mime.first; content; content = content->next) + { void *handle; + if (soap->fmimereadopen && ((handle = soap->fmimereadopen(soap, (void*)content->ptr, content->id, content->type, content->description)) || soap->error)) + { size_t size = content->size; + if (!handle) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimereadopen failed\n")); + return soap->error; + } + if (soap_putmimehdr(soap, content)) + return soap->error; + if (!size) + { if ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming MIME\n")); + do + { size = soap->fmimeread(soap, handle, soap->tmpbuf, sizeof(soap->tmpbuf)); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread returned %lu bytes\n", (unsigned long)size)); + if (soap_send_raw(soap, soap->tmpbuf, size)) + break; + } while (size); + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error: cannot chunk streaming MIME (no HTTP chunking)\n")); + } + } + else + { do + { size_t bufsize; + if (size < sizeof(soap->tmpbuf)) + bufsize = size; + else + bufsize = sizeof(soap->tmpbuf); + if (!(bufsize = soap->fmimeread(soap, handle, soap->tmpbuf, bufsize))) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size)); + soap->error = SOAP_EOF; + break; + } + if (soap_send_raw(soap, soap->tmpbuf, bufsize)) + break; + size -= bufsize; + } while (size); + } + if (soap->fmimereadclose) + soap->fmimereadclose(soap, handle); + } + else + { if (soap_putmimehdr(soap, content) + || soap_send_raw(soap, content->ptr, content->size)) + return soap->error; + } + } + return soap_send3(soap, "\r\n--", soap->mime.boundary, "--"); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_dime(struct soap *soap) +{ soap->omode |= SOAP_ENC_DIME; + soap->dime.first = NULL; + soap->dime.last = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_mime(struct soap *soap, const char *boundary, const char *start) +{ soap->omode |= SOAP_ENC_MIME; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = soap_strdup(soap, boundary); + soap->mime.start = soap_strdup(soap, start); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_clr_dime(struct soap *soap) +{ soap->omode &= ~SOAP_ENC_DIME; + soap->dime.first = NULL; + soap->dime.last = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_clr_mime(struct soap *soap) +{ soap->omode &= ~SOAP_ENC_MIME; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = NULL; + soap->mime.start = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static struct soap_multipart* +soap_new_multipart(struct soap *soap, struct soap_multipart **first, struct soap_multipart **last, char *ptr, size_t size) +{ struct soap_multipart *content; + content = (struct soap_multipart*)soap_malloc(soap, sizeof(struct soap_multipart)); + if (content) + { content->next = NULL; + content->ptr = ptr; + content->size = size; + content->id = NULL; + content->type = NULL; + content->options = NULL; + content->encoding = SOAP_MIME_NONE; + content->location = NULL; + content->description = NULL; + if (!*first) + *first = content; + if (*last) + (*last)->next = content; + *last = content; + } + return content; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_dime_attachment(struct soap *soap, char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option) +{ struct soap_multipart *content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, ptr, size); + if (!content) + return SOAP_EOM; + content->id = soap_strdup(soap, id); + content->type = soap_strdup(soap, type); + content->options = soap_dime_option(soap, optype, option); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_mime_attachment(struct soap *soap, char *ptr, size_t size, enum soap_mime_encoding encoding, const char *type, const char *id, const char *location, const char *description) +{ struct soap_multipart *content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, ptr, size); + if (!content) + return SOAP_EOM; + content->id = soap_strdup(soap, id); + content->type = soap_strdup(soap, type); + content->encoding = encoding; + content->location = soap_strdup(soap, location); + content->description = soap_strdup(soap, description); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +struct soap_multipart* +SOAP_FMAC2 +soap_next_multipart(struct soap_multipart *content) +{ if (content) + return content->next; + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static void +soap_select_mime_boundary(struct soap *soap) +{ while (!soap->mime.boundary || soap_valid_mime_boundary(soap)) + { register char *s = soap->mime.boundary; + register size_t n = 0; + if (s) + n = strlen(s); + if (n < 16) + { n = 64; + s = soap->mime.boundary = (char*)soap_malloc(soap, n + 1); + if (!s) + return; + } + strcpy(s, "=="); + s += 2; + n -= 4; + while (n) + { *s++ = soap_base64o[soap_random & 0x3F]; + n--; + } + strcpy(s, "=="); + } + if (!soap->mime.start) + soap->mime.start = ""; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static int +soap_valid_mime_boundary(struct soap *soap) +{ register struct soap_multipart *content; + register size_t k; + if (soap->fmimeread) + return SOAP_OK; + k = strlen(soap->mime.boundary); + for (content = soap->mime.first; content; content = content->next) + { if (content->ptr && content->size >= k) + { register const char *p = (const char*)content->ptr; + register size_t i; + for (i = 0; i < content->size - k; i++, p++) + { if (!strncmp(p, soap->mime.boundary, k)) + return SOAP_ERR; + } + } + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************\ + * + * HTTP cookie handling + * +\******************************************************************************/ + +#ifdef WITH_COOKIES +/******************************************************************************/ +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_encode_cookie(const char *s, char *t, size_t len) +{ register int c; + register size_t n = len; + while ((c = *s++) && --n > 0) + { if (c > ' ' && c < 128 && !strchr("()<>@,;:\\\"/[]?={}", c)) + *t++ = c; + else if (n > 2) + { *t++ = '%'; + *t++ = (c >> 4) + (c > 159 ? '7' : '0'); + c &= 0xF; + *t++ = c + (c > 9 ? '7' : '0'); + n -= 2; + } + else + break; + } + *t = '\0'; + return len - n; +} + +/******************************************************************************/ +SOAP_FMAC1 +struct soap_cookie* +SOAP_FMAC2 +soap_cookie(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + size_t n; + if (!domain) + domain = soap->cookie_domain; + if (!path) + path = soap->cookie_path; + if (!path) + path = SOAP_STR_EOS; + else if (*path == '/') + path++; + n = strlen(path); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Search cookie %s domain=%s path=%s\n", name, domain?domain:"(null)", path?path:"(null)")); + for (p = soap->cookies; p; p = p->next) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie in database: %s=%s domain=%s path=%s env=%hd\n", p->name, p->value?p->value:"(null)", p->domain?p->domain:"(null)", p->path?p->path:"(null)", p->env)); + if (!strcmp(p->name, name) + && p->domain + && p->path + && !strcmp(p->domain, domain) + && !strncmp(p->path, path, n)) + break; + } + return p; +} + +/******************************************************************************/ +SOAP_FMAC1 +struct soap_cookie* +SOAP_FMAC2 +soap_set_cookie(struct soap *soap, const char *name, const char *value, const char *domain, const char *path) +{ struct soap_cookie **p, *q; + int n; + if (!domain) + domain = soap->cookie_domain; + if (!path) + path = soap->cookie_path; + if (!path) + path = SOAP_STR_EOS; + else if (*path == '/') + path++; + q = soap_cookie(soap, name, domain, path); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set %scookie: %s=%s domain=%s path=%s\n", q ? "" : "new ", name, value?value:"(null)", domain?domain:"(null)", path?path:"(null)")); + if (!q) + { if ((q = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie)))) + { if ((q->name = (char*)SOAP_MALLOC(soap, strlen(name)+1))) + strcpy(q->name, name); + q->value = NULL; + q->domain = NULL; + q->path = NULL; + q->expire = 0; + q->maxage = -1; + q->version = 1; + q->secure = 0; + q->modified = 0; + for (p = &soap->cookies, n = soap->cookie_max; *p && n; p = &(*p)->next, n--) + if (!strcmp((*p)->name, name) && (*p)->path && path && strcmp((*p)->path, path) < 0) + break; + if (n) + { q->next = *p; + *p = q; + } + else + { SOAP_FREE(soap, q->name); + SOAP_FREE(soap, q); + q = NULL; + } + } + } + else + q->modified = 1; + if (q) + { if (q->value) + { SOAP_FREE(soap, q->value); + q->value = NULL; + } + if (q->domain) + { SOAP_FREE(soap, q->domain); + q->domain = NULL; + } + if (q->path) + { SOAP_FREE(soap, q->path); + q->path = NULL; + } + if (value && *value && (q->value = (char*)SOAP_MALLOC(soap, strlen(value)+1))) + strcpy(q->value, value); + if (domain && (q->domain = (char*)SOAP_MALLOC(soap, strlen(domain)+1))) + strcpy(q->domain, domain); + if (path && (q->path = (char*)SOAP_MALLOC(soap, strlen(path)+1))) + strcpy(q->path, path); + q->session = 1; + q->env = 0; + } + return q; +} + +/******************************************************************************/ +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_clr_cookie(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie **p, *q; + if (!domain) + domain = soap->cookie_domain; + if (!domain) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error in clear cookie %s: cookie domain not set\n", name?name:"(null)")); + return; + } + if (!path) + path = soap->cookie_path; + if (!path) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error in clear cookie %s: cookie path not set\n", name?name:"(null)")); + return; + } + if (*path == '/') + path++; + for (p = &soap->cookies, q = *p; q; q = *p) + { if (!strcmp(q->name, name) && !strcmp(q->domain, domain) && !strncmp(q->path, path, strlen(q->path))) + { if (q->value) + SOAP_FREE(soap, q->value); + if (q->domain) + SOAP_FREE(soap, q->domain); + if (q->path) + SOAP_FREE(soap, q->path); + *p = q->next; + SOAP_FREE(soap, q); + } + else + p = &q->next; + } +} + +/******************************************************************************/ +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + return p->value; + return NULL; +} + +/******************************************************************************/ +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_env_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path)) && p->env) + return p->value; + return NULL; +} + +/******************************************************************************/ +SOAP_FMAC1 +time_t +SOAP_FMAC2 +soap_cookie_expire(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + return p->expire; + return -1; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_cookie_expire(struct soap *soap, const char *name, long expire, const char *domain, const char *path) +{ struct soap_cookie *p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set cookie expiration max-age %ld: %s domain=%s path=%s\n", expire, name, domain?domain:"(null)", path?path:"(null)")); + if ((p = soap_cookie(soap, name, domain, path))) + { p->maxage = expire; + p->modified = 1; + return SOAP_OK; + } + return SOAP_ERR; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + { p->session = 1; + p->modified = 1; + return SOAP_OK; + } + return SOAP_ERR; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_clr_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + { p->session = 0; + p->modified = 1; + return SOAP_OK; + } + return SOAP_ERR; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putsetcookies(struct soap *soap) +{ struct soap_cookie *p; + char *s, tmp[4096]; + const char *t; + for (p = soap->cookies; p; p = p->next) + { + if (p->modified +#ifdef WITH_OPENSSL + || (!p->env && !soap->ssl == !p->secure) +#endif + ) + { s = tmp; + if (p->name) + s += soap_encode_cookie(p->name, s, tmp-s+4064); + if (p->value && *p->value) + { *s++ = '='; + s += soap_encode_cookie(p->value, s, tmp-s+4064); + } + if (p->domain && (int)strlen(p->domain) < tmp-s+4064) + { strcpy(s, ";Domain="); + strcat(s, p->domain); + } + else if (soap->cookie_domain && (int)strlen(soap->cookie_domain) < tmp-s+4064) + { strcpy(s, ";Domain="); + strcat(s, soap->cookie_domain); + } + strcat(s, ";Path=/"); + s += strlen(s); + if (p->path) + t = p->path; + else + t = soap->cookie_path; + if (t) + { if (*t == '/') + t++; + if ((int)strlen(t) < tmp-s+4064) + { if (strchr(t, '%')) /* already URL encoded? */ + { strcpy(s, t); + s += strlen(s); + } + else + s += soap_encode_cookie(t, s, tmp-s+4064); + } + } + if (p->version > 0 && s-tmp < 4060) + { sprintf(s, ";Version=%u", p->version); + s += strlen(s); + } + if (p->maxage >= 0 && s-tmp < 4060) + { sprintf(s, ";Max-Age=%ld", p->maxage); + s += strlen(s); + } + if (s-tmp < 4073 + && (p->secure +#ifdef WITH_OPENSSL + || soap->ssl +#endif + )) + strcpy(s, ";Secure"); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set-Cookie: %s\n", tmp)); + if ((soap->error = soap->fposthdr(soap, "Set-Cookie", tmp))) + return soap->error; + } + } + return SOAP_OK; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putcookies(struct soap *soap, const char *domain, const char *path, int secure) +{ struct soap_cookie **p, *q; + unsigned int version = 0; + time_t now = time(NULL); + char *s, tmp[4096]; + p = &soap->cookies; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending cookies for domain=%s path=%s\n", domain, path)); + if (*path == '/') + path++; + while ((q = *p)) + { if (q->expire && now > q->expire) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie %s expired\n", q->name)); + SOAP_FREE(soap, q->name); + if (q->value) + SOAP_FREE(soap, q->value); + if (q->domain) + SOAP_FREE(soap, q->domain); + if (q->path) + SOAP_FREE(soap, q->path); + *p = q->next; + SOAP_FREE(soap, q); + } + else + { int flag; + char *t = q->domain; + size_t n = 0; + if (!t) + flag = 1; + else + { const char *r = strchr(t, ':'); + if (r) + n = r - t; + else + n = strlen(t); + flag = !strncmp(t, domain, n); + } + /* domain-level cookies */ + if (!flag) + { struct hostent *hostent = gethostbyname((char*)domain); + if (hostent) + { const char *r = strchr(hostent->h_name, '.'); + if (!r) + r = hostent->h_name; + flag = !strncmp(t, r, n); + } + } + if (flag + && (!q->path || !strncmp(q->path, path, strlen(q->path))) + && (!q->secure || secure)) + { s = tmp; + if (q->version != version) + { sprintf(s, "$Version=%u;", q->version); + version = q->version; + } + if (q->name) + s += soap_encode_cookie(q->name, s, tmp-s+4080); + if (q->value && *q->value) + { *s++ = '='; + s += soap_encode_cookie(q->value, s, tmp-s+4080); + } + if (q->path && *q->path && (int)strlen(q->path) < tmp-s+4080) + { sprintf(s, ";$Path=\"/%s\"", (*q->path == '/' ? q->path + 1 : q->path)); + s += strlen(s); + } + if (q->domain && (int)strlen(q->domain) < tmp-s+4080) + sprintf(s, ";$Domain=\"%s\"", q->domain); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie: %s\n", tmp)); + if ((soap->error = soap->fposthdr(soap, "Cookie", tmp))) + return soap->error; + } + p = &q->next; + } + } + return SOAP_OK; +} + +/******************************************************************************/ +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_getcookies(struct soap *soap, const char *val) +{ struct soap_cookie *p = NULL, *q; + const char *s; + char *t, tmp[4096]; /* cookie size is up to 4096 bytes [RFC2109] */ + char *domain = NULL; + char *path = NULL; + unsigned int version = 0; + time_t now = time(NULL); + if (!val) + return; + s = val; + while (*s) + { s = soap_decode_key(tmp, sizeof(tmp), s); + if (!soap_tag_cmp(tmp, "$Version")) + { if ((s = soap_decode_val(tmp, sizeof(tmp), s))) + { if (p) + p->version = (int)atol(tmp); + else + version = (int)atol(tmp); + } + } + else if (!soap_tag_cmp(tmp, "$Path")) + { s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) + strcpy(t, tmp); + } + else + t = NULL; + if (p) + { if (p->path) + SOAP_FREE(soap, p->path); + p->path = t; + } + else + { if (path) + SOAP_FREE(soap, path); + path = t; + } + } + else if (!soap_tag_cmp(tmp, "$Domain")) + { s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) + strcpy(t, tmp); + } + else + t = NULL; + if (p) + { if (p->domain) + SOAP_FREE(soap, p->domain); + p->domain = t; + } + else + { if (domain) + SOAP_FREE(soap, domain); + domain = t; + } + } + else if (p && !soap_tag_cmp(tmp, "Path")) + { if (p->path) + SOAP_FREE(soap, p->path); + s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { if ((p->path = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) + strcpy(p->path, tmp); + } + else + p->path = NULL; + } + else if (p && !soap_tag_cmp(tmp, "Domain")) + { if (p->domain) + SOAP_FREE(soap, p->domain); + s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { if ((p->domain = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) + strcpy(p->domain, tmp); + } + else + p->domain = NULL; + } + else if (p && !soap_tag_cmp(tmp, "Version")) + { s = soap_decode_val(tmp, sizeof(tmp), s); + p->version = (unsigned int)atol(tmp); + } + else if (p && !soap_tag_cmp(tmp, "Max-Age")) + { s = soap_decode_val(tmp, sizeof(tmp), s); + p->expire = now + atol(tmp); + } + else if (p && !soap_tag_cmp(tmp, "Expires")) + { struct tm T; + char a[3]; + static const char mns[] = "anebarprayunulugepctovec"; + s = soap_decode_val(tmp, sizeof(tmp), s); + if (strlen(tmp) > 20) + { memset((void*)&T, 0, sizeof(T)); + a[0] = tmp[4]; + a[1] = tmp[5]; + a[2] = '\0'; + T.tm_mday = (int)atol(a); + a[0] = tmp[8]; + a[1] = tmp[9]; + T.tm_mon = (int)(strstr(mns, a) - mns) / 2; + a[0] = tmp[11]; + a[1] = tmp[12]; + T.tm_year = 100 + (int)atol(a); + a[0] = tmp[13]; + a[1] = tmp[14]; + T.tm_hour = (int)atol(a); + a[0] = tmp[16]; + a[1] = tmp[17]; + T.tm_min = (int)atol(a); + a[0] = tmp[19]; + a[1] = tmp[20]; + T.tm_sec = (int)atol(a); + p->expire = soap_timegm(&T); + } + } + else if (p && !soap_tag_cmp(tmp, "Secure")) + p->secure = 1; + else + { if (p) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie %s=%s domain=%s path=%s expire=%ld secure=%d\n", p->name, p->value?p->value:"(null)", p->domain?p->domain:"(null)", p->path?p->path:"(null)", p->expire, p->secure)); + if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path))) + { q->version = p->version; + q->expire = p->expire; + q->secure = p->secure; + q->env = 1; + } + if (p->name) + SOAP_FREE(soap, p->name); + if (p->value) + SOAP_FREE(soap, p->value); + if (p->domain) + SOAP_FREE(soap, p->domain); + if (p->path) + SOAP_FREE(soap, p->path); + SOAP_FREE(soap, p); + } + if ((p = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie)))) + { p->name = (char*)SOAP_MALLOC(soap, strlen(tmp)+1); + strcpy(p->name, tmp); + s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { p->value = (char*)SOAP_MALLOC(soap, strlen(tmp)+1); + strcpy(p->value, tmp); + } + else + p->value = NULL; + if (domain) + p->domain = domain; + else if (*soap->host) + { p->domain = (char*)SOAP_MALLOC(soap, strlen(soap->host)+1); + strcpy(p->domain, soap->host); + } + else + p->domain = NULL; + if (path) + p->path = path; + else if (soap->path && *soap->path) + { p->path = (char*)SOAP_MALLOC(soap, strlen(soap->path)+1); + strcpy(p->path, soap->path); + } + else + { p->path = (char*)SOAP_MALLOC(soap, 2); + strcpy(p->path, "/"); + } + p->expire = 0; + p->secure = 0; + p->version = version; + } + } + } + if (p) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie %s=%s domain=%s path=%s expire=%ld secure=%d\n", p->name, p->value?p->value:"(null)", p->domain?p->domain:"(null)", p->path?p->path:"(null)", p->expire, p->secure)); + if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path))) + { q->version = p->version; + q->expire = p->expire; + q->secure = p->secure; + q->env = 1; + } + if (p->name) + SOAP_FREE(soap, p->name); + if (p->value) + SOAP_FREE(soap, p->value); + if (p->domain) + SOAP_FREE(soap, p->domain); + if (p->path) + SOAP_FREE(soap, p->path); + SOAP_FREE(soap, p); + } + if (domain) + SOAP_FREE(soap, domain); + if (path) + SOAP_FREE(soap, path); +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getenv_cookies(struct soap *soap) +{ struct soap_cookie *p; + const char *s; + char key[4096], val[4096]; /* cookie size is up to 4096 bytes [RFC2109] */ + if (!(s = getenv("HTTP_COOKIE"))) + return SOAP_ERR; + do + { s = soap_decode_key(key, sizeof(key), s); + s = soap_decode_val(val, sizeof(val), s); + p = soap_set_cookie(soap, key, val, NULL, NULL); + if (p) + p->env = 1; + } while (*s); + return SOAP_OK; +} + +/******************************************************************************/ +SOAP_FMAC1 +struct soap_cookie* +SOAP_FMAC2 +soap_copy_cookies(struct soap *copy, const struct soap *soap) +{ struct soap_cookie *p, **q, *r; + q = &r; + for (p = soap->cookies; p; p = p->next) + { if (!(*q = (struct soap_cookie*)SOAP_MALLOC(copy, sizeof(struct soap_cookie)))) + return r; + **q = *p; + if (p->name) + { if (((*q)->name = (char*)SOAP_MALLOC(copy, strlen(p->name)+1))) + strcpy((*q)->name, p->name); + } + if (p->value) + { if (((*q)->value = (char*)SOAP_MALLOC(copy, strlen(p->value)+1))) + strcpy((*q)->value, p->value); + } + if (p->domain) + { if (((*q)->domain = (char*)SOAP_MALLOC(copy, strlen(p->domain)+1))) + strcpy((*q)->domain, p->domain); + } + if (p->path) + { if (((*q)->path = (char*)SOAP_MALLOC(copy, strlen(p->path)+1))) + strcpy((*q)->path, p->path); + } + q = &(*q)->next; + } + *q = NULL; + return r; +} + +/******************************************************************************/ +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_free_cookies(struct soap *soap) +{ struct soap_cookie *p; + for (p = soap->cookies; p; p = soap->cookies) + { soap->cookies = p->next; + SOAP_FREE(soap, p->name); + if (p->value) + SOAP_FREE(soap, p->value); + if (p->domain) + SOAP_FREE(soap, p->domain); + if (p->path) + SOAP_FREE(soap, p->path); + SOAP_FREE(soap, p); + } +} + +/******************************************************************************/ +#endif /* WITH_COOKIES */ + +/******************************************************************************/ +#ifdef WITH_GZIP +#ifndef PALM_1 +static int +soap_getgziphdr(struct soap *soap) +{ int i; + soap_wchar c = 0, f = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get gzip header\n")); + for (i = 0; i < 9; i++) + { if ((int)(c = soap_get1(soap) == EOF)) + return soap->error = SOAP_EOF; + if (i == 2) + f = c; + } + if (f & 0x04) /* FEXTRA */ + { for (i = soap_get1(soap) | (soap_get1(soap) << 8); i; i--) + { if ((int)soap_get1(soap) == EOF) + return soap->error = SOAP_EOF; + } + } + if (f & 0x08) /* FNAME */ + { do + c = soap_get1(soap); + while (c && (int)c != EOF); + } + if ((int)c != EOF && (f & 0x10)) /* FCOMMENT */ + { do + c = soap_get1(soap); + while (c && (int)c != EOF); + } + if ((int)c != EOF && (f & 0x01)) /* FHCRC */ + { if ((int)(c = soap_get1(soap)) != EOF) + c = soap_get1(soap); + } + if ((int)c == EOF) + return soap->error = SOAP_EOF; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_begin_recv(struct soap *soap) +{ soap_wchar c; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing for input\n")); + soap->error = SOAP_OK; + soap_free_temp(soap); + soap_set_local_namespaces(soap); + soap->version = 0; /* don't assume we're parsing SOAP content by default */ +#ifndef WITH_NOIDREF + soap_free_iht(soap); +#endif + if ((soap->imode & SOAP_IO) == SOAP_IO_CHUNK) + soap->omode |= SOAP_IO_CHUNK; + soap->imode &= ~SOAP_IO; + soap->mode = soap->imode; + if (!soap->keep_alive) + { soap->buflen = 0; + soap->bufidx = 0; + } + if (!(soap->mode & SOAP_IO_KEEPALIVE)) + soap->keep_alive = 0; + soap->ahead = 0; + soap->peeked = 0; + soap->level = 0; + soap->part = SOAP_BEGIN; + soap->alloced = 0; + soap->count = 0; + soap->length = 0; + soap->cdata = 0; + *soap->endpoint = '\0'; + soap->action = NULL; + soap->header = NULL; + soap->fault = NULL; + soap->status = 0; +#ifndef WITH_LEANER + soap->dom = NULL; + soap->dime.chunksize = 0; + soap->dime.buflen = 0; + soap->dime.list = NULL; + soap->dime.first = NULL; + soap->dime.last = NULL; + soap->mime.list = NULL; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = NULL; + soap->mime.start = NULL; + soap->xlist = NULL; +#endif +#ifdef WIN32 +#ifndef UNDER_CE +#ifndef WITH_FASTCGI + if (!soap_valid_socket(soap->socket)) +#ifdef __BORLANDC__ + setmode(soap->recvfd, O_BINARY); +#else + _setmode(soap->recvfd, _O_BINARY); +#endif +#endif +#endif +#endif +#ifdef WITH_ZLIB + soap->mode &= ~SOAP_ENC_ZLIB; + soap->zlib_in = SOAP_ZLIB_NONE; + soap->zlib_out = SOAP_ZLIB_NONE; + soap->d_stream->next_in = Z_NULL; + soap->d_stream->avail_in = 0; + soap->d_stream->next_out = (Byte*)soap->buf; + soap->d_stream->avail_out = SOAP_BUFLEN; + soap->z_ratio_in = 1.0; +#endif +#ifndef WITH_LEANER + if (soap->fprepareinit) + soap->fprepareinit(soap); +#endif + c = soap_getchar(soap); +#ifdef WITH_GZIP + if (c == 0x1F) + { if (soap_getgziphdr(soap)) + return soap->error; + if (inflateInit2(soap->d_stream, -MAX_WBITS) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; + soap->zlib_state = SOAP_ZLIB_INFLATE; + soap->mode |= SOAP_ENC_ZLIB; + soap->zlib_in = SOAP_ZLIB_GZIP; + soap->z_crc = crc32(0L, NULL, 0); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n")); + if (!soap->z_buf) + soap->z_buf = (char*)SOAP_MALLOC(soap, SOAP_BUFLEN); + memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); + /* should not chunk over plain transport, so why bother to check? */ + /* if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) */ + /* soap->z_buflen = soap->bufidx; */ + /* else */ + soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx); + soap->d_stream->avail_in = soap->buflen - soap->bufidx; + soap->z_buflen = soap->buflen; + soap->buflen = soap->bufidx; + c = soap_getchar(soap); + } +#endif +#ifndef WITH_LEANER + if (c == '-' && soap_get0(soap) == '-') + soap->mode |= SOAP_ENC_MIME; + else if ((c & 0xFFFC) == (SOAP_DIME_VERSION | SOAP_DIME_MB) && (soap_get0(soap) & 0xFFF0) == 0x20) + soap->mode |= SOAP_ENC_DIME; + else +#endif + { while (soap_blank(c)) + c = soap_getchar(soap); + } + if ((int)c == EOF) + return soap->error = SOAP_EOF; + soap_unget(soap, c); +#ifndef WITH_NOHTTP + /* if not XML or (start of)BOM or MIME/DIME/ZLIB, assume HTTP header */ + if (c != '<' && c != 0xEF && !(soap->mode & (SOAP_ENC_MIME | SOAP_ENC_DIME | SOAP_ENC_ZLIB))) + { soap->mode &= ~SOAP_IO; + soap->error = soap->fparse(soap); + if (soap->error && soap->error < SOAP_STOP) + { soap->keep_alive = 0; /* force close later */ + return soap->error; + } + if (soap->error == SOAP_STOP) + return soap->error; + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) + { soap->chunkbuflen = soap->buflen; + soap->buflen = soap->bufidx; + soap->chunksize = 0; + } +#ifndef WITH_LEANER + else if (soap->fpreparerecv && soap->buflen != soap->bufidx) + soap->fpreparerecv(soap, soap->buf + soap->bufidx, soap->buflen - soap->bufidx); +#endif + /* Note: fparse should not use soap_unget to push back last char */ + if (soap_get0(soap) == (int)EOF) + { if (soap->status == 200) + return soap->error = SOAP_NO_DATA; + return soap->error = soap->status; + } +#ifdef WITH_ZLIB + if (soap->zlib_in != SOAP_ZLIB_NONE) + { +#ifdef WITH_GZIP + if (soap->zlib_in != SOAP_ZLIB_DEFLATE) + { c = soap_get1(soap); + if (c == 0x1F) + { if (soap_getgziphdr(soap)) + return soap->error; + if (inflateInit2(soap->d_stream, -MAX_WBITS) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; + soap->z_crc = crc32(0L, NULL, 0); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n")); + } + else + { soap_revget1(soap); + if (inflateInit(soap->d_stream) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; + soap->zlib_in = SOAP_ZLIB_DEFLATE; + } + } + else +#endif + if (inflateInit(soap->d_stream) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; + soap->zlib_state = SOAP_ZLIB_INFLATE; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate initialized\n")); + soap->mode |= SOAP_ENC_ZLIB; + if (!soap->z_buf) + soap->z_buf = (char*)SOAP_MALLOC(soap, SOAP_BUFLEN); + memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); + soap->d_stream->next_in = (Byte*)(soap->z_buf + soap->bufidx); + soap->d_stream->avail_in = soap->buflen - soap->bufidx; + soap->z_buflen = soap->buflen; + soap->buflen = soap->bufidx; + } +#endif + if (soap->error) + { if (soap->error == SOAP_FORM && soap->fform) + { soap->error = soap->fform(soap); + if (soap->error == SOAP_OK) + soap->error = SOAP_STOP; /* prevents further processing */ + } + return soap->error; + } + } +#endif +#ifndef WITH_LEANER + if (soap->mode & SOAP_ENC_MIME) + { if (soap_getmimehdr(soap)) + return soap->error; + if (soap->mime.start) + { do + { if (!soap->mime.last->id) + break; + if (!soap_match_cid(soap, soap->mime.start, soap->mime.last->id)) + break; + } while (soap_get_mime_attachment(soap, NULL)); + } + if (soap_get_header_attribute(soap, soap->mime.first->type, "application/dime")) + soap->mode |= SOAP_ENC_DIME; + } + if (soap->mode & SOAP_ENC_DIME) + { if (soap_getdimehdr(soap)) + return soap->error; + if (soap->dime.flags & SOAP_DIME_CF) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked DIME SOAP message\n")); + soap->dime.chunksize = soap->dime.size; + if (soap->buflen - soap->bufidx >= soap->dime.chunksize) + { soap->dime.buflen = soap->buflen; + soap->buflen = soap->bufidx + soap->dime.chunksize; + } + else + soap->dime.chunksize -= soap->buflen - soap->bufidx; + } + soap->count = soap->buflen - soap->bufidx; + } +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_parse(struct soap *soap) +{ char header[SOAP_HDRLEN], *s; + unsigned short httpcmd = 0, status = 0, k = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Waiting for HTTP request/response...\n")); + *soap->endpoint = '\0'; + soap->length = 0; + soap->userid = NULL; + soap->passwd = NULL; + soap->action = NULL; + soap->authrealm = NULL; + soap->proxy_from = NULL; + soap->http_content = NULL; + soap->status = 0; + do + { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) + { if (soap->error == SOAP_EOF) + return SOAP_EOF; + return soap->error = 414; + } + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP status: %s\n", soap->msgbuf)); + for (;;) + { if (soap_getline(soap, header, SOAP_HDRLEN)) + { if (soap->error == SOAP_EOF) + { soap->error = SOAP_OK; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "EOF in HTTP header, continue anyway\n")); + break; + } + return soap->error; + } + if (!*header) + break; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP header: %s\n", header)); + s = strchr(header, ':'); + if (s) + { char *t; + *s = '\0'; + do s++; + while (*s && *s <= 32); + if (*s == '"') + s++; + t = s + strlen(s) - 1; + while (t > s && *t <= 32) + t--; + if (t >= s && *t == '"') + t--; + t[1] = '\0'; + if ((soap->error = soap->fparsehdr(soap, header, s))) + { if (soap->error < SOAP_STOP) + return soap->error; + status = soap->error; + soap->error = SOAP_OK; + } + } + } + if ((s = strchr(soap->msgbuf, ' '))) + { k = (unsigned short)soap_strtoul(s, &s, 10); + if (!soap_blank(*s)) + k = 0; + } + else + k = 0; + } while (k == 100); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Finished HTTP header parsing, status = %d\n", k)); + s = strstr(soap->msgbuf, "HTTP/"); + if (s && s[7] != '1') + { if (soap->keep_alive == 1) + soap->keep_alive = 0; + if (k == 0 && (soap->omode & SOAP_IO) == SOAP_IO_CHUNK) /* k == 0 for HTTP request */ + { soap->imode |= SOAP_IO_CHUNK; + soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE; + } + } + if (soap->keep_alive < 0) + soap->keep_alive = 1; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Keep alive connection = %d\n", soap->keep_alive)); + if (k == 0) + { size_t l = 0; + if (s) + { if (!strncmp(soap->msgbuf, "POST ", l = 5)) + httpcmd = 1; + else if (!strncmp(soap->msgbuf, "GET ", l = 4)) + httpcmd = 2; + else if (!strncmp(soap->msgbuf, "PUT ", l = 4)) + httpcmd = 3; + else if (!strncmp(soap->msgbuf, "DELETE ", l = 7)) + httpcmd = 4; + else if (!strncmp(soap->msgbuf, "HEAD ", l = 5)) + httpcmd = 5; + } + if (s && httpcmd) + { size_t m = strlen(soap->endpoint); + size_t n = m + (s - soap->msgbuf) - l - 1; + if (m > n) + m = n; + if (n >= sizeof(soap->endpoint)) + n = sizeof(soap->endpoint) - 1; + strncpy(soap->path, soap->msgbuf + l, n - m); + soap->path[n - m] = '\0'; + strcat(soap->endpoint, soap->path); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Target endpoint='%s'\n", soap->endpoint)); + if (httpcmd > 1) + { switch (httpcmd) + { case 2: soap->error = soap->fget(soap); break; + case 3: soap->error = soap->fput(soap); break; + case 4: soap->error = soap->fdel(soap); break; + case 5: soap->error = soap->fhead(soap); break; + default: soap->error = SOAP_HTTP_METHOD; break; + } + if (soap->error == SOAP_OK) + soap->error = SOAP_STOP; /* prevents further processing */ + return soap->error; + } + if (status) + return soap->error = status; + } + else if (status) + return soap->error = status; + else if (s) + return soap->error = 405; + } + soap->status = k; + /* Status OK (HTTP 200) */ + if (k == 0 || k == 200) + return SOAP_OK; + /* Status 201 (Created), 202 (Accepted), ... and HTTP 400 and 500 errors. + Only keep parsing HTTP body when content-length>0 or chunked is set. + */ + if (((k > 200 && k <= 299) || k == 400 || k == 500) && (soap->length > 0 || (soap->imode & SOAP_IO) == SOAP_IO_CHUNK)) + return SOAP_OK; + /* HTTP 400 and 500 headers are supposed to set content-length or chunked. + For those that don't we keep parsing the body only if content type is + given and connection closes. + */ + if ((k == 400 || k == 500) && (soap->http_content || soap->keep_alive == 0)) + return SOAP_OK; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP error %d\n", k)); + return soap_set_receiver_error(soap, "HTTP Error", soap->msgbuf, k); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_parse_header(struct soap *soap, const char *key, const char *val) +{ if (!soap_tag_cmp(key, "Host")) + { +#ifdef WITH_OPENSSL + if (soap->imode & SOAP_ENC_SSL) + strcpy(soap->endpoint, "https://"); + else +#endif + strcpy(soap->endpoint, "http://"); + strncat(soap->endpoint, val, sizeof(soap->endpoint) - 8); + soap->endpoint[sizeof(soap->endpoint) - 1] = '\0'; + } +#ifndef WITH_LEANER + else if (!soap_tag_cmp(key, "Content-Type")) + { const char *action; + soap->http_content = soap_strdup(soap, val); + if (soap_get_header_attribute(soap, val, "application/dime")) + soap->mode |= SOAP_ENC_DIME; + else if (soap_get_header_attribute(soap, val, "multipart/related") + || soap_get_header_attribute(soap, val, "multipart/form-data")) + { soap->mime.boundary = soap_strdup(soap, soap_get_header_attribute(soap, val, "boundary")); + soap->mime.start = soap_strdup(soap, soap_get_header_attribute(soap, val, "start")); + soap->mode |= SOAP_ENC_MIME; + } + action = soap_get_header_attribute(soap, val, "action"); + if (action) + { if (*action == '"') + { soap->action = soap_strdup(soap, action + 1); + soap->action[strlen(soap->action) - 1] = '\0'; + } + else + soap->action = soap_strdup(soap, action); + } + } +#endif + else if (!soap_tag_cmp(key, "Content-Length")) + { soap->length = soap_strtoul(val, NULL, 10); + } + else if (!soap_tag_cmp(key, "Content-Encoding")) + { if (!soap_tag_cmp(val, "deflate")) +#ifdef WITH_ZLIB + soap->zlib_in = SOAP_ZLIB_DEFLATE; +#else + return SOAP_ZLIB_ERROR; +#endif + else if (!soap_tag_cmp(val, "gzip")) +#ifdef WITH_GZIP + soap->zlib_in = SOAP_ZLIB_GZIP; +#else + return SOAP_ZLIB_ERROR; +#endif + } +#ifdef WITH_ZLIB + else if (!soap_tag_cmp(key, "Accept-Encoding")) + { +#ifdef WITH_GZIP + if (strchr(val, '*') || soap_get_header_attribute(soap, val, "gzip")) + soap->zlib_out = SOAP_ZLIB_GZIP; + else +#endif + if (strchr(val, '*') || soap_get_header_attribute(soap, val, "deflate")) + soap->zlib_out = SOAP_ZLIB_DEFLATE; + else + soap->zlib_out = SOAP_ZLIB_NONE; + } +#endif + else if (!soap_tag_cmp(key, "Transfer-Encoding")) + { soap->mode &= ~SOAP_IO; + if (!soap_tag_cmp(val, "chunked")) + soap->mode |= SOAP_IO_CHUNK; + } + else if (!soap_tag_cmp(key, "Connection")) + { if (!soap_tag_cmp(val, "keep-alive")) + soap->keep_alive = -soap->keep_alive; + else if (!soap_tag_cmp(val, "close")) + soap->keep_alive = 0; + } +#ifndef WITH_LEAN + else if (!soap_tag_cmp(key, "Authorization")) + { if (!soap_tag_cmp(val, "Basic *")) + { int n; + char *s; + soap_base642s(soap, val + 6, soap->tmpbuf, sizeof(soap->tmpbuf) - 1, &n); + soap->tmpbuf[n] = '\0'; + if ((s = strchr(soap->tmpbuf, ':'))) + { *s = '\0'; + soap->userid = soap_strdup(soap, soap->tmpbuf); + soap->passwd = soap_strdup(soap, s + 1); + } + } + } + else if (!soap_tag_cmp(key, "WWW-Authenticate")) + { soap->authrealm = soap_strdup(soap, soap_get_header_attribute(soap, val + 6, "realm")); + } + else if (!soap_tag_cmp(key, "Expect")) + { if (!soap_tag_cmp(val, "100-continue")) + { if ((soap->error = soap->fposthdr(soap, "HTTP/1.1 100 Continue", NULL)) + || (soap->error = soap->fposthdr(soap, NULL, NULL))) + return soap->error; + } + } +#endif + else if (!soap_tag_cmp(key, "SOAPAction")) + { if (*val == '"') + { soap->action = soap_strdup(soap, val + 1); + soap->action[strlen(soap->action) - 1] = '\0'; + } + else + soap->action = soap_strdup(soap, val); + } + else if (!soap_tag_cmp(key, "Location")) + { strncpy(soap->endpoint, val, sizeof(soap->endpoint)); + soap->endpoint[sizeof(soap->endpoint) - 1] = '\0'; + } + else if (!soap_tag_cmp(key, "X-Forwarded-For")) + { soap->proxy_from = soap_strdup(soap, val); + } +#ifdef WITH_COOKIES + else if (!soap_tag_cmp(key, "Cookie") + || !soap_tag_cmp(key, "Cookie2") + || !soap_tag_cmp(key, "Set-Cookie") + || !soap_tag_cmp(key, "Set-Cookie2")) + { soap_getcookies(soap, val); + } +#endif + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_get_header_attribute(struct soap *soap, const char *line, const char *key) +{ register const char *s = line; + if (s) + { while (*s) + { register short flag; + s = soap_decode_key(soap->tmpbuf, sizeof(soap->tmpbuf), s); + flag = soap_tag_cmp(soap->tmpbuf, key); + s = soap_decode_val(soap->tmpbuf, sizeof(soap->tmpbuf), s); + if (!flag) + return soap->tmpbuf; + } + } + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_decode_key(char *buf, size_t len, const char *val) +{ return soap_decode(buf, len, val, "=,;"); +} +#endif +#endif + +/******************************************************************************/ +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_decode_val(char *buf, size_t len, const char *val) +{ if (*val != '=') + { *buf = '\0'; + return val; + } + return soap_decode(buf, len, val + 1, ",;"); +} +#endif +#endif + +/******************************************************************************/ +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +#ifndef PALM_1 +static const char* +soap_decode(char *buf, size_t len, const char *val, const char *sep) +{ const char *s; + char *t = buf; + for (s = val; *s; s++) + if (*s != ' ' && *s != '\t' && !strchr(sep, *s)) + break; + if (*s == '"') + { s++; + while (*s && *s != '"' && --len) + *t++ = *s++; + } + else + { while (*s && !soap_blank(*s) && !strchr(sep, *s) && --len) + { if (*s == '%') + { *t++ = ((s[1] >= 'A' ? (s[1] & 0x7) + 9 : s[1] - '0') << 4) + + (s[2] >= 'A' ? (s[2] & 0x7) + 9 : s[2] - '0'); + s += 3; + } + else + *t++ = *s++; + } + } + *t = '\0'; + while (*s && !strchr(sep, *s)) + s++; + return s; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_envelope_begin_out(struct soap *soap) +{ +#ifndef WITH_LEANER + size_t n = 0; + if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && soap->mime.start && strlen(soap->mime.boundary) + strlen(soap->mime.start) < sizeof(soap->tmpbuf) - 80 ) + { const char *s; + if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) + s = "application/dime"; + else if (soap->version == 2) + { if (soap->mode & SOAP_ENC_MTOM) + s = "application/xop+xml; charset=utf-8; type=\"application/soap+xml\""; + else + s = "application/soap+xml; charset=utf-8"; + } + else + s = "text/xml; charset=utf-8"; + sprintf(soap->tmpbuf, "--%s\r\nContent-Type: %s\r\nContent-Transfer-Encoding: binary\r\nContent-ID: %s\r\n\r\n", soap->mime.boundary, s, soap->mime.start); + n = strlen(soap->tmpbuf); + if (soap_send_raw(soap, soap->tmpbuf, n)) + return soap->error; + } + if (soap->mode & SOAP_IO_LENGTH) + soap->dime.size = soap->count; /* DIME in MIME correction */ + if (!(soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME)) + { if (soap_putdimehdr(soap)) + return soap->error; + } +#endif + soap->part = SOAP_IN_ENVELOPE; + return soap_element_begin_out(soap, "SOAP-ENV:Envelope", 0, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_envelope_end_out(struct soap *soap) +{ if (soap_element_end_out(soap, "SOAP-ENV:Envelope")) + return soap->error; +#ifndef WITH_LEANER + if ((soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) + { soap->dime.size = soap->count - soap->dime.size; /* DIME in MIME correction */ + sprintf(soap->id, soap->dime_id_format, 0); + soap->dime.id = soap->id; + if (soap->local_namespaces) + { if (soap->local_namespaces[0].out) + soap->dime.type = (char*)soap->local_namespaces[0].out; + else + soap->dime.type = (char*)soap->local_namespaces[0].ns; + } + soap->dime.options = NULL; + soap->dime.flags = SOAP_DIME_MB | SOAP_DIME_ABSURI; + if (!soap->dime.first) + soap->dime.flags |= SOAP_DIME_ME; + soap->count += 12 + ((strlen(soap->dime.id)+3)&(~3)) + (soap->dime.type ? ((strlen(soap->dime.type)+3)&(~3)) : 0); + } + if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) + return soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3); +#endif + soap->part = SOAP_END_ENVELOPE; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_envelope_begin_in(struct soap *soap) +{ register struct Namespace *p; + soap->part = SOAP_IN_ENVELOPE; + if (soap_element_begin_in(soap, "SOAP-ENV:Envelope", 0, NULL)) + { +#ifndef WITH_LEAN + if (soap->error == SOAP_TAG_MISMATCH && !soap_element_begin_in(soap, "html", 0, NULL)) + { /* get HTML from buffer, stop receiving to avoid HTML parsing issues */ + char *s; +#ifndef WITH_NOIO + size_t (*f)(struct soap*, char*, size_t) = soap->frecv; + soap->frecv = frecv_stop; +#endif + soap_revert(soap); + s = soap_string_in(soap, 1, -1, -1); +#ifndef WITH_NOIO + soap->frecv = f; +#endif + return soap_set_receiver_error(soap, "HTTP Error", s, SOAP_HTTP_ERROR); + } +#endif + if (soap->error == SOAP_TAG_MISMATCH) + return soap->error = SOAP_VERSIONMISMATCH; + return soap->error; + } + p = soap->local_namespaces; + if (p) + { const char *ns = p[0].out; + if (!ns) + ns = p[0].ns; + if (!strcmp(ns, soap_env1)) + { soap->version = 1; /* make sure we use SOAP 1.1 */ + if (p[1].out) + SOAP_FREE(soap, p[1].out); + if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc1)))) + strcpy(p[1].out, soap_enc1); + } + else if (!strcmp(ns, soap_env2)) + { soap->version = 2; /* make sure we use SOAP 1.2 */ + if (p[1].out) + SOAP_FREE(soap, p[1].out); + if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc2)))) + strcpy(p[1].out, soap_enc2); + } + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_envelope_end_in(struct soap *soap) +{ soap->part = SOAP_END_ENVELOPE; + return soap_element_end_in(soap, "SOAP-ENV:Envelope"); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_body_begin_out(struct soap *soap) +{ soap->part = SOAP_IN_BODY; + if (soap->version == 1) + soap->encoding = 1; +#ifndef WITH_LEAN + if ((soap->mode & SOAP_XML_SEC) && soap_set_attr(soap, "wsu:Id", "Body")) + return soap->error; +#endif + if (soap_element(soap, "SOAP-ENV:Body", 0, NULL)) + return soap->error; + return soap_element_start_end_out(soap, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_body_end_out(struct soap *soap) +{ if (soap_element_end_out(soap, "SOAP-ENV:Body")) + return soap->error; + soap->part = SOAP_END_BODY; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_body_begin_in(struct soap *soap) +{ soap->part = SOAP_IN_BODY; + if (soap_element_begin_in(soap, "SOAP-ENV:Body", 0, NULL)) + return soap->error; + if (!soap->body) + soap->part = SOAP_NO_BODY; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_body_end_in(struct soap *soap) +{ if (soap->part == SOAP_NO_BODY) + return SOAP_OK; + soap->part = SOAP_END_BODY; + return soap_element_end_in(soap, "SOAP-ENV:Body"); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv_header(struct soap *soap) +{ if (soap_getheader(soap) && soap->error == SOAP_TAG_MISMATCH) + soap->error = SOAP_OK; + else if (soap->error == SOAP_OK && soap->fheader) + soap->error = soap->fheader(soap); + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_endpoint(struct soap *soap, const char *endpoint) +{ register const char *s; + register size_t i, n; + soap->endpoint[0] = '\0'; + soap->host[0] = '\0'; + soap->path[0] = '/'; + soap->path[1] = '\0'; + soap->port = 80; + if (!endpoint || !*endpoint) + return; +#ifdef WITH_OPENSSL + if (!soap_tag_cmp(endpoint, "https:*")) + soap->port = 443; +#endif + strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint) - 1); + soap->endpoint[sizeof(soap->endpoint) - 1] = '\0'; + s = strchr(endpoint, ':'); + if (s && s[1] == '/' && s[2] == '/') + s += 3; + else + s = endpoint; + n = strlen(s); + if (n >= sizeof(soap->host)) + n = sizeof(soap->host) - 1; +#ifdef WITH_IPV6 + if (s[0] == '[') + { s++; + for (i = 0; i < n; i++) + { if (s[i] == ']') + { s++; + --n; + break; + } + soap->host[i] = s[i]; + } + } + else + { for (i = 0; i < n; i++) + { soap->host[i] = s[i]; + if (s[i] == '/' || s[i] == ':') + break; + } + } +#else + for (i = 0; i < n; i++) + { soap->host[i] = s[i]; + if (s[i] == '/' || s[i] == ':') + break; + } +#endif + soap->host[i] = '\0'; + if (s[i] == ':') + { soap->port = (int)atol(s + i + 1); + for (i++; i < n; i++) + if (s[i] == '/') + break; + } + if (i < n && s[i]) + { strncpy(soap->path, s + i, sizeof(soap->path)); + soap->path[sizeof(soap->path) - 1] = '\0'; + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_connect(struct soap *soap, const char *endpoint, const char *action) +{ return soap_connect_command(soap, SOAP_POST, endpoint, action); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_connect_command(struct soap *soap, int http_command, const char *endpoint, const char *action) +{ char host[sizeof(soap->host)]; + int port; + size_t count; + soap->error = SOAP_OK; + strcpy(host, soap->host); /* save previous host name to compare */ + port = soap->port; /* save previous port to compare */ + soap->status = http_command; + soap_set_endpoint(soap, endpoint); +#ifndef WITH_LEANER + if (soap->fconnect) + { if ((soap->error = soap->fconnect(soap, endpoint, soap->host, soap->port))) + return soap->error; + } + else +#endif + if (soap->fopen && *soap->host) + { if (!soap->keep_alive || !soap_valid_socket(soap->socket) || strcmp(soap->host, host) || soap->port != port || !soap->fpoll || soap->fpoll(soap)) + { soap->keep_alive = 0; /* to force close */ + soap->omode &= ~SOAP_IO_UDP; /* to force close */ + soap_closesock(soap); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Connect/reconnect to host='%s' path='%s' port=%d\n", soap->host, soap->path, soap->port)); +#ifndef WITH_LEAN + if (!strncmp(endpoint, "soap.udp:", 9)) + soap->omode |= SOAP_IO_UDP; +#endif + soap->socket = soap->fopen(soap, endpoint, soap->host, soap->port); + if (soap->error) + return soap->error; + soap->keep_alive = ((soap->omode & SOAP_IO_KEEPALIVE) != 0); + } + } + count = soap_count_attachments(soap); + if (soap_begin_send(soap)) + return soap->error; + if (http_command != SOAP_POST) + { soap->mode &= ~SOAP_IO; + soap->mode |= SOAP_IO_BUFFER; + } +#ifndef WITH_NOHTTP + soap->action = soap_strdup(soap, action); + if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML) && endpoint) + { unsigned int k = soap->mode; + soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB); + if ((k & SOAP_IO) != SOAP_IO_FLUSH) + soap->mode |= SOAP_IO_BUFFER; + if ((soap->error = soap->fpost(soap, endpoint, soap->host, soap->port, soap->path, action, count))) + return soap->error; +#ifndef WITH_LEANER + if ((k & SOAP_IO) == SOAP_IO_CHUNK) + { if (soap_flush(soap)) + return soap->error; + } +#endif + soap->mode = k; + } + if (http_command != SOAP_POST) + return soap_end_send(soap); +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_s2base64(struct soap *soap, const unsigned char *s, char *t, int n) +{ register int i; + register unsigned long m; + register char *p; + if (!t) + t = (char*)soap_malloc(soap, (n + 2) / 3 * 4 + 1); + if (!t) + { soap->error = SOAP_EOM; + return NULL; + } + p = t; + t[0] = '\0'; + if (!s) + return p; + for (; n > 2; n -= 3, s += 3) + { m = s[0]; + m = (m << 8) | s[1]; + m = (m << 8) | s[2]; + for (i = 4; i > 0; m >>= 6) + t[--i] = soap_base64o[m & 0x3F]; + t += 4; + } + t[0] = '\0'; + if (n > 0) + { m = 0; + for (i = 0; i < n; i++) + m = (m << 8) | *s++; + for (; i < 3; i++) + m <<= 8; + for (i++; i > 0; m >>= 6) + t[--i] = soap_base64o[m & 0x3F]; + for (i = 3; i > n; i--) + t[i] = '='; + t[4] = '\0'; + } + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_base642s(struct soap *soap, const char *s, char *t, size_t l, int *n) +{ register int i, j, c; + register unsigned long m; + register const char *p; + if (!s || !*s) + { if (n) + *n = 0; + if (soap->error) + return NULL; + return SOAP_NON_NULL; + } + if (!t) + { l = (strlen(s) + 3) / 4 * 3; + t = (char*)soap_malloc(soap, l); + } + if (!t) + { soap->error = SOAP_EOM; + return NULL; + } + p = t; + if (n) + *n = 0; + for (;;) + { for (i = 0; i < SOAP_BLKLEN; i++) + { m = 0; + j = 0; + while (j < 4) + { c = *s++; + if (c == '=' || !c) + { i *= 3; + switch (j) + { case 2: + *t++ = (char)((m >> 4) & 0xFF); + i++; + break; + case 3: + *t++ = (char)((m >> 10) & 0xFF); + *t++ = (char)((m >> 2) & 0xFF); + i += 2; + } + if (n) + *n += i; + return p; + } + c -= '+'; + if (c >= 0 && c <= 79) + { int b = soap_base64i[c]; + if (b >= 64) + { soap->error = SOAP_TYPE; + return NULL; + } + m = (m << 6) + b; + j++; + } + else if (!soap_blank(c + '+')) + { soap->error = SOAP_TYPE; + return NULL; + } + } + *t++ = (char)((m >> 16) & 0xFF); + *t++ = (char)((m >> 8) & 0xFF); + *t++ = (char)(m & 0xFF); + if (l < 3) + { if (n) + *n += i; + return p; + } + l -= 3; + } + if (n) + *n += 3 * SOAP_BLKLEN; + } +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_s2hex(struct soap *soap, const unsigned char *s, char *t, int n) +{ register char *p; + if (!t) + t = (char*)soap_malloc(soap, 2 * n + 1); + if (!t) + { soap->error = SOAP_EOM; + return NULL; + } + p = t; + t[0] = '\0'; + if (s) + { for (; n > 0; n--) + { register int m = *s++; + *t++ = (char)((m >> 4) + (m > 159 ? 'a' - 10 : '0')); + m &= 0x0F; + *t++ = (char)(m + (m > 9 ? 'a' - 10 : '0')); + } + } + *t++ = '\0'; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_hex2s(struct soap *soap, const char *s, char *t, size_t l, int *n) +{ register const char *p; + if (!s || !*s) + { if (n) + *n = 0; + if (soap->error) + return NULL; + return SOAP_NON_NULL; + } + if (!t) + { l = strlen(s) / 2; + t = (char*)soap_malloc(soap, l); + } + if (!t) + { soap->error = SOAP_EOM; + return NULL; + } + p = t; + while (l) + { register int d1, d2; + d1 = *s++; + if (!d1) + break; + d2 = *s++; + if (!d2) + break; + *t++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'); + l--; + } + if (n) + *n = (int)(t - p); + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_puthttphdr(struct soap *soap, int status, size_t count) +{ if (soap->status != SOAP_GET) + { register const char *s = "text/xml; charset=utf-8"; + register int err = SOAP_OK; +#ifndef WITH_LEANER + register const char *r = NULL; +#endif + if (status == SOAP_FILE && soap->http_content) + s = soap->http_content; + else if (status == SOAP_HTML) + s = "text/html; charset=utf-8"; + else if (count || ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK)) + { if (soap->version == 2) + s = "application/soap+xml; charset=utf-8"; + } +#ifndef WITH_LEANER + if (soap->mode & (SOAP_ENC_DIME | SOAP_ENC_MTOM)) + { if (soap->mode & SOAP_ENC_MTOM) + { r = s; + s = "application/xop+xml; charset=utf-8"; + } + else + s = "application/dime"; + } + if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && strlen(soap->mime.boundary) + strlen(soap->mime.start ? soap->mime.start : SOAP_STR_EOS) < sizeof(soap->tmpbuf) - 80) + { register const char *t = strchr(s, ';'); + sprintf(soap->tmpbuf, "multipart/related; boundary=\"%s\"; type=\"", soap->mime.boundary); + if (t) + strncat(soap->tmpbuf, s, t - s); + else + strcat(soap->tmpbuf, s); + if (soap->mime.start) + { strcat(soap->tmpbuf, "\"; start=\""); + strcat(soap->tmpbuf, soap->mime.start); + } + strcat(soap->tmpbuf, "\""); + if (r) + { strcat(soap->tmpbuf, "; start-info=\""); + strcat(soap->tmpbuf, r); + strcat(soap->tmpbuf, "\""); + } + s = soap->tmpbuf; + } +#endif + if (s && (err = soap->fposthdr(soap, "Content-Type", s))) + return err; +#ifdef WITH_ZLIB + if (soap->omode & SOAP_ENC_ZLIB) + { +#ifdef WITH_GZIP + err = soap->fposthdr(soap, "Content-Encoding", soap->zlib_out == SOAP_ZLIB_DEFLATE ? "deflate" : "gzip"); +#else + err = soap->fposthdr(soap, "Content-Encoding", "deflate"); +#endif + if (err) + return err; + } +#endif +#ifndef WITH_LEANER + if ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK) + err = soap->fposthdr(soap, "Transfer-Encoding", "chunked"); + else +#endif + if (s) + { sprintf(soap->tmpbuf, "%lu", (unsigned long)count); + err = soap->fposthdr(soap, "Content-Length", soap->tmpbuf); + } + if (err) + return err; + } + return soap->fposthdr(soap, "Connection", soap->keep_alive ? "keep-alive" : "close"); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_get(struct soap *soap) +{ return SOAP_GET_METHOD; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_put(struct soap *soap) +{ return SOAP_PUT_METHOD; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_del(struct soap *soap) +{ return SOAP_DEL_METHOD; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_head(struct soap *soap) +{ return SOAP_HEAD_METHOD; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_post(struct soap *soap, const char *endpoint, const char *host, int port, const char *path, const char *action, size_t count) +{ register const char *s; + register int err; + if (soap->status == SOAP_GET) + s = "GET"; + else + s = "POST"; +#ifdef PALM + if (!endpoint || (soap_tag_cmp(endpoint, "http:*") && soap_tag_cmp(endpoint, "https:*") && strncmp(endpoint, "httpg:", 6)) && strncmp(endpoint, "_beam:", 6) && strncmp(endpoint, "_local:", 7) && strncmp(endpoint, "_btobex:", 8)) +#else + if (!endpoint || (soap_tag_cmp(endpoint, "http:*") && soap_tag_cmp(endpoint, "https:*") && strncmp(endpoint, "httpg:", 6))) +#endif + return SOAP_OK; + if (strlen(endpoint) + strlen(soap->http_version) > sizeof(soap->tmpbuf) - 80) + return soap->error = SOAP_EOM; + if (soap->proxy_host && soap_tag_cmp(endpoint, "https:*")) + sprintf(soap->tmpbuf, "%s %s HTTP/%s", s, endpoint, soap->http_version); + else + sprintf(soap->tmpbuf, "%s /%s HTTP/%s", s, (*path == '/' ? path + 1 : path), soap->http_version); + if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return err; +#ifdef WITH_OPENSSL + if ((soap->ssl && soap->port != 443) || (!soap->ssl && soap->port != 80)) + sprintf(soap->tmpbuf, "%s:%d", host, port); + else + strcpy(soap->tmpbuf, host); +#else + if (port != 80) + sprintf(soap->tmpbuf, "%s:%d", host, port); + else + strcpy(soap->tmpbuf, host); +#endif + if ((err = soap->fposthdr(soap, "Host", soap->tmpbuf)) + || (err = soap->fposthdr(soap, "User-Agent", "gSOAP/2.7")) + || (err = soap_puthttphdr(soap, SOAP_OK, count))) + return err; +#ifdef WITH_ZLIB +#ifdef WITH_GZIP + if ((err = soap->fposthdr(soap, "Accept-Encoding", "gzip, deflate"))) +#else + if ((err = soap->fposthdr(soap, "Accept-Encoding", "deflate"))) +#endif + return err; +#endif +#ifndef WITH_LEAN + if (soap->userid && soap->passwd && strlen(soap->userid) + strlen(soap->passwd) < 761) + { sprintf(soap->tmpbuf + 262, "%s:%s", soap->userid, soap->passwd); + strcpy(soap->tmpbuf, "Basic "); + soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262)); + if ((err = soap->fposthdr(soap, "Authorization", soap->tmpbuf))) + return err; + } + if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761) + { sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd); + strcpy(soap->tmpbuf, "Basic "); + soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262)); + if ((err = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf))) + return err; + } +#endif +#ifdef WITH_COOKIES +#ifdef WITH_OPENSSL + if (soap_putcookies(soap, host, path, soap->ssl != NULL)) + return soap->error; +#else + if (soap_putcookies(soap, host, path, 0)) + return soap->error; +#endif +#endif + if (soap->status != SOAP_GET && (soap->version == 1 || (action && *action && strlen(action) < sizeof(soap->tmpbuf) - 2))) + { sprintf(soap->tmpbuf, "\"%s\"", action?action:""); + if ((err = soap->fposthdr(soap, "SOAPAction", soap->tmpbuf))) + return err; + } + return soap->fposthdr(soap, NULL, NULL); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_send_header(struct soap *soap, const char *s) +{ register const char *t; + do + { t = strchr(s, '\n'); /* disallow \n in HTTP headers */ + if (!t) + t = s + strlen(s); + if (soap_send_raw(soap, s, t - s)) + return soap->error; + s = t + 1; + } while (*t); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_post_header(struct soap *soap, const char *key, const char *val) +{ if (key) + { if (http_send_header(soap, key)) + return soap->error; + if (val && (soap_send_raw(soap, ": ", 2) || http_send_header(soap, val))) + return soap->error; + } + return soap_send_raw(soap, "\r\n", 2); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_response(struct soap *soap, int status, size_t count) +{ register int err; +#ifdef WMW_RPM_IO + if (soap->rpmreqid) + httpOutputEnable(soap->rpmreqid); +#endif + if (strlen(soap->http_version) > 4) + return soap->error = SOAP_EOM; + if (!status || status == SOAP_HTML || status == SOAP_FILE) + { const char *s; + if (count || ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK)) + s = "200 OK"; + else + s = "202 ACCEPTED"; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Status = %s\n", s)); +#ifdef WMW_RPM_IO + if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */ +#else + if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application */ +#endif + { sprintf(soap->tmpbuf, "HTTP/%s %s", soap->http_version, s); + if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return err; + } + else if ((err = soap->fposthdr(soap, "Status", s))) + return err; + } + else if (status >= 200 && status < 600) + { sprintf(soap->tmpbuf, "HTTP/%s %d %s", soap->http_version, status, http_error(soap, status)); + if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return err; +#ifndef WITH_LEAN + if (status == 401) + { sprintf(soap->tmpbuf, "Basic realm=\"%s\"", (soap->authrealm ? strlen(soap->authrealm) : 18) < sizeof(soap->tmpbuf) - 14 ? soap->authrealm : "gSOAP Web Service"); + if ((err = soap->fposthdr(soap, "WWW-Authenticate", soap->tmpbuf))) + return err; + } + else if ((status >= 301 && status <= 303) || status == 307) + { if ((err = soap->fposthdr(soap, "Location", soap->endpoint))) + return err; + } +#endif + } + else + { const char *s = *soap_faultcode(soap); + if (soap->version == 2 && (!s || !strcmp(s, "SOAP-ENV:Sender"))) + s = "400 Bad Request"; + else + s = "500 Internal Server Error"; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error %s (status=%d)\n", s, status)); +#ifdef WMW_RPM_IO + if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */ +#else + if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application */ +#endif + { sprintf(soap->tmpbuf, "HTTP/%s %s", soap->http_version, s); + if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return err; + } + else if ((err = soap->fposthdr(soap, "Status", s))) /* CGI */ + return err; + } + if ((err = soap->fposthdr(soap, "Server", "gSOAP/2.7")) + || (err = soap_puthttphdr(soap, status, count))) + return err; +#ifdef WITH_COOKIES + if (soap_putsetcookies(soap)) + return soap->error; +#endif + return soap->fposthdr(soap, NULL, NULL); +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_response(struct soap *soap, int status) +{ register size_t count; + if (!(soap->omode & (SOAP_ENC_XML | SOAP_IO_STORE /* this tests for chunking too */)) + && (status == SOAP_HTML || status == SOAP_FILE)) + { soap->omode &= ~SOAP_IO; + soap->omode |= SOAP_IO_STORE; + } + soap->status = status; + count = soap_count_attachments(soap); + if (soap_begin_send(soap)) + return soap->error; +#ifndef WITH_NOHTTP + if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML)) + { register int n = soap->mode; + soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB); + if ((n & SOAP_IO) != SOAP_IO_FLUSH) + soap->mode |= SOAP_IO_BUFFER; + if ((soap->error = soap->fresponse(soap, status, count))) + return soap->error; +#ifndef WITH_LEANER + if ((n & SOAP_IO) == SOAP_IO_CHUNK) + { if (soap_flush(soap)) + return soap->error; + } +#endif + soap->mode = n; + } +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static const char* +soap_set_validation_fault(struct soap *soap, const char *s, const char *t) +{ if (*soap->tag) + sprintf(soap->msgbuf, "Validation constraint violation: %s%s in element <%s>", s, t?t:SOAP_STR_EOS, soap->tag); + else + sprintf(soap->msgbuf, "Validation constraint violation: %s%s", s, t?t:SOAP_STR_EOS); + return soap->msgbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_fault(struct soap *soap) +{ const char **c = soap_faultcode(soap); + const char **s = soap_faultstring(soap); + if (soap->fseterror) + soap->fseterror(soap, c, s); + if (!*c) + { if (soap->version == 2) + *c = "SOAP-ENV:Sender"; + else + *c = "SOAP-ENV:Client"; + } + if (*s) + return; + switch (soap->error) + { +#ifndef WITH_LEAN + case SOAP_CLI_FAULT: + *s = "Client fault"; + break; + case SOAP_SVR_FAULT: + *s = "Server fault"; + break; + case SOAP_TAG_MISMATCH: + *s = soap_set_validation_fault(soap, "tag name or namespace mismatch", NULL); + break; + case SOAP_TYPE: + *s = soap_set_validation_fault(soap, "data type mismatch ", soap->type); + break; + case SOAP_SYNTAX_ERROR: + *s = "Well-formedness violation"; + break; + case SOAP_NO_TAG: + *s = "No XML element tag"; + break; + case SOAP_MUSTUNDERSTAND: + *c = "SOAP-ENV:MustUnderstand"; + sprintf(soap->msgbuf, "The data in element '%s' must be understood but cannot be handled", soap->tag); + *s = soap->msgbuf; + break; + case SOAP_VERSIONMISMATCH: + *c = "SOAP-ENV:VersionMismatch"; + *s = "Invalid SOAP message or SOAP version mismatch"; + break; + case SOAP_DATAENCODINGUNKNOWN: + *c = "SOAP-ENV:DataEncodingUnknown"; + *s = "Unsupported SOAP data encoding"; + break; + case SOAP_NAMESPACE: + *s = soap_set_validation_fault(soap, "namespace error", NULL); + break; + case SOAP_USER_ERROR: + *s = "User error"; + break; + case SOAP_FATAL_ERROR: + *s = "Fatal error"; + break; + case SOAP_NO_METHOD: + sprintf(soap->msgbuf, "Method '%s' not implemented: method name or namespace not recognized", soap->tag); + *s = soap->msgbuf; + break; + case SOAP_NO_DATA: + *s = "Data required for operation"; + break; + case SOAP_GET_METHOD: + *s = "HTTP GET method not implemented"; + break; + case SOAP_PUT_METHOD: + *s = "HTTP PUT method not implemented"; + break; + case SOAP_HEAD_METHOD: + *s = "HTTP HEAD method not implemented"; + break; + case SOAP_HTTP_METHOD: + *s = "HTTP method not implemented"; + break; + case SOAP_EOM: + *s = "Out of memory"; + break; + case SOAP_MOE: + *s = "Memory overflow or memory corruption error"; + break; + case SOAP_HDR: + *s = "Header line too long"; + break; + case SOAP_IOB: + *s = "Array index out of bounds"; + break; + case SOAP_NULL: + *s = soap_set_validation_fault(soap, "nil not allowed", NULL); + break; + case SOAP_DUPLICATE_ID: + *s = soap_set_validation_fault(soap, "multiple definitions of id ", soap->id); + if (soap->version == 2) + *soap_faultsubcode(soap) = "SOAP-ENC:DuplicateID"; + break; + case SOAP_MISSING_ID: + *s = soap_set_validation_fault(soap, "missing id for ref ", soap->id); + if (soap->version == 2) + *soap_faultsubcode(soap) = "SOAP-ENC:MissingID"; + break; + case SOAP_HREF: + *s = soap_set_validation_fault(soap, "incompatible object type ref/id pair ", soap->id); + break; + case SOAP_FAULT: + break; +#ifndef WITH_NOIO + case SOAP_UDP_ERROR: + *s = "Message too large for UDP packet"; + break; + case SOAP_TCP_ERROR: + *s = tcp_error(soap); + break; +#endif + case SOAP_HTTP_ERROR: + *s = "An HTTP processing error occurred"; + break; + case SOAP_SSL_ERROR: +#ifdef WITH_OPENSSL + *s = "SSL error"; +#else + *s = "OpenSSL not installed: recompile with -DWITH_OPENSSL"; +#endif + break; + case SOAP_PLUGIN_ERROR: + *s = "Plugin registry error"; + break; + case SOAP_DIME_ERROR: + *s = "DIME format error"; + break; + case SOAP_DIME_HREF: + *s = "DIME href to missing attachment"; + break; + case SOAP_DIME_MISMATCH: + *s = "DIME version/transmission error"; + break; + case SOAP_DIME_END: + *s = "End of DIME error"; + break; + case SOAP_MIME_ERROR: + *s = "MIME format error"; + break; + case SOAP_MIME_HREF: + *s = "MIME href to missing attachment"; + break; + case SOAP_MIME_END: + *s = "End of MIME error"; + break; + case SOAP_ZLIB_ERROR: +#ifdef WITH_ZLIB + sprintf(soap->msgbuf, "Zlib/gzip error: '%s'", soap->d_stream->msg?soap->d_stream->msg:""); + *s = soap->msgbuf; +#else + *s = "Zlib/gzip not installed for (de)compression: recompile with -DWITH_GZIP"; +#endif + break; + case SOAP_REQUIRED: + *s = soap_set_validation_fault(soap, "missing required attribute", NULL); + break; + case SOAP_PROHIBITED: + *s = soap_set_validation_fault(soap, "prohibited attribute present", NULL); + break; + case SOAP_OCCURS: + *s = soap_set_validation_fault(soap, "occurrence violation", NULL); + break; + case SOAP_LENGTH: + *s = soap_set_validation_fault(soap, "content length violation", NULL); + break; + case SOAP_FD_EXCEEDED: + *s = "Maximum number of open connections was reached"; + break; + case SOAP_STOP: + *s = "Stopped: no response sent"; + break; +#endif + case SOAP_EOF: +#ifndef WITH_NOIO + strcpy(soap->msgbuf, soap_strerror(soap)); +#ifndef WITH_LEAN + if (strlen(soap->msgbuf) + 25 < sizeof(soap->msgbuf)) + { memmove(soap->msgbuf + 25, soap->msgbuf, strlen(soap->msgbuf) + 1); + memcpy(soap->msgbuf, "End of file or no input: ", 25); + } +#endif + *s = soap->msgbuf; + break; +#else + *s = "End of file or no input"; + break; +#endif + default: +#ifndef WITH_NOHTTP +#ifndef WITH_LEAN + if (soap->error > 200 && soap->error < 600) + { sprintf(soap->msgbuf, "HTTP Error: %d %s", soap->error, http_error(soap, soap->error)); + *s = soap->msgbuf; + } + else +#endif +#endif + { sprintf(soap->msgbuf, "Error %d", soap->error); + *s = soap->msgbuf; + } + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send_fault(struct soap *soap) +{ register int status = soap->error; + int r = 1; + if (status == SOAP_STOP) + return status; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Sending back fault struct for error code %d\n", soap->error)); + soap->keep_alive = 0; /* to terminate connection */ + soap_set_fault(soap); +#ifndef WITH_NOIO +#ifndef WITH_LEAN + if (soap_valid_socket(soap->socket)) + { struct timeval timeout; + fd_set rfd, sfd; + timeout.tv_sec = 0; + timeout.tv_usec = 0; + FD_ZERO(&rfd); + FD_ZERO(&sfd); + FD_SET(soap->socket, &rfd); + FD_SET(soap->socket, &sfd); + r = select((int)soap->socket + 1, &rfd, &sfd, NULL, &timeout); + if (r > 0) + { if (!FD_ISSET(soap->socket, &sfd) + || (FD_ISSET(soap->socket, &rfd) + && recv(soap->socket, soap->tmpbuf, 1, MSG_PEEK) < 0)) + r = 0; + } + } +#endif +#endif + if ((status != SOAP_EOF || (!soap->recv_timeout && !soap->send_timeout)) && r > 0) + { soap->error = SOAP_OK; + soap_serializeheader(soap); + soap_serializefault(soap); + soap_begin_count(soap); + if (soap->mode & SOAP_IO_LENGTH) + { soap_envelope_begin_out(soap); + soap_putheader(soap); + soap_body_begin_out(soap); + soap_putfault(soap); + soap_body_end_out(soap); + soap_envelope_end_out(soap); + } + soap_end_count(soap); + if (soap_response(soap, status) + || soap_envelope_begin_out(soap) + || soap_putheader(soap) + || soap_body_begin_out(soap) + || soap_putfault(soap) + || soap_body_end_out(soap) + || soap_envelope_end_out(soap)) + return soap_closesock(soap); + soap_end_send(soap); + } + soap->error = status; + return soap_closesock(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv_fault(struct soap *soap) +{ register int status = soap->error; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Receiving SOAP Fault\n")); + soap->error = SOAP_OK; + if (soap_getfault(soap)) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Error: soap_get_soapfault() failed. Is this a SOAP message at all?\n")); + *soap_faultcode(soap) = (soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client"); + soap->error = status; + soap_set_fault(soap); + } + else + { register const char *s = *soap_faultcode(soap); + if (!soap_match_tag(soap, s, "SOAP-ENV:Server") || !soap_match_tag(soap, s, "SOAP-ENV:Receiver")) + status = SOAP_SVR_FAULT; + else if (!soap_match_tag(soap, s, "SOAP-ENV:Client") || !soap_match_tag(soap, s, "SOAP-ENV:Sender")) + status = SOAP_CLI_FAULT; + else if (!soap_match_tag(soap, s, "SOAP-ENV:MustUnderstand")) + status = SOAP_MUSTUNDERSTAND; + else if (!soap_match_tag(soap, s, "SOAP-ENV:VersionMismatch")) + status = SOAP_VERSIONMISMATCH; + else + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Fault code %s\n", s)); + status = SOAP_FAULT; + } + if (soap_body_end_in(soap) + || soap_envelope_end_in(soap) + || soap_end_recv(soap)) + return soap_closesock(soap); + soap->error = status; + } + return soap_closesock(soap); +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send_empty_response(struct soap *soap, int httpstatuscode) +{ register soap_mode m = soap->omode; + soap->count = 0; + if ((m & SOAP_IO) == SOAP_IO_CHUNK) + { soap->omode &= ~SOAP_IO_CHUNK; + soap->omode |= SOAP_IO_BUFFER; + } + if (soap_response(soap, httpstatuscode) || soap_end_send(soap)) + { soap->omode = m; + return soap_closesock(soap); + } + soap->omode = m; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv_empty_response(struct soap *soap) +{ if (soap_begin_recv(soap) || soap_end_recv(soap)) + { if (soap->error != 202) + return soap_closesock(soap); + soap->error = SOAP_OK; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static const char* +soap_strerror(struct soap *soap) +{ register int err = soap->errnum; + if (err) + { +#ifndef WIN32 + return strerror(err); +#else +#ifndef UNDER_CE + DWORD len; + *soap->msgbuf = '\0'; + len = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)soap->msgbuf, (DWORD)sizeof(soap->msgbuf), NULL); +#else + DWORD i, len; + *soap->msgbuf = '\0'; + len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0, (LPTSTR)soap->msgbuf, (DWORD)(sizeof(soap->msgbuf)/sizeof(TCHAR)), NULL); + for (i = 0; i <= len; i++) + { if (((TCHAR*)soap->msgbuf)[i] < 0x80) + soap->msgbuf[i] = (char)((TCHAR*)soap->msgbuf)[i]; + else + soap->msgbuf[i] = '?'; + } +#endif + return soap->msgbuf; +#endif + } +#ifndef WITH_LEAN + if (soap->recv_timeout > 0) + { if (soap->send_timeout > 0) + sprintf(soap->msgbuf, "Operation interrupted or timed out after %ds send or %ds receive delay", soap->send_timeout, soap->recv_timeout); + else + sprintf(soap->msgbuf, "Operation interrupted or timed out after %ds receive delay", soap->recv_timeout); + return soap->msgbuf; + } +#endif + return "Operation interrupted or timed out"; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +static int +soap_set_error(struct soap *soap, const char *faultcode, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML, int soaperror) +{ *soap_faultcode(soap) = faultcode; + if (faultsubcodeQName) + *soap_faultsubcode(soap) = faultsubcodeQName; + *soap_faultstring(soap) = faultstring; + if (faultdetailXML && *faultdetailXML) + { register const char **s = soap_faultdetail(soap); + if (s) + *s = faultdetailXML; + } + return soap->error = soaperror; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_sender_error(struct soap *soap, const char *faultstring, const char *faultdetailXML, int soaperror) +{ return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", NULL, faultstring, faultdetailXML, soaperror); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_receiver_error(struct soap *soap, const char *faultstring, const char *faultdetailXML, int soaperror) +{ return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", NULL, faultstring, faultdetailXML, soaperror); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +static int +soap_copy_fault(struct soap *soap, const char *faultcode, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML) +{ char *r = NULL, *s = NULL, *t = NULL; + if (faultsubcodeQName) + r = soap_strdup(soap, faultsubcodeQName); + if (faultstring) + s = soap_strdup(soap, faultstring); + if (faultdetailXML) + t = soap_strdup(soap, faultdetailXML); + return soap_set_error(soap, faultcode, r, s, t, SOAP_FAULT); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_sender_fault(struct soap *soap, const char *faultstring, const char *faultdetailXML) +{ return soap_sender_fault_subcode(soap, NULL, faultstring, faultdetailXML); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_sender_fault_subcode(struct soap *soap, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML) +{ return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", faultsubcodeQName, faultstring, faultdetailXML); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_receiver_fault(struct soap *soap, const char *faultstring, const char *faultdetailXML) +{ return soap_receiver_fault_subcode(soap, NULL, faultstring, faultdetailXML); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_receiver_fault_subcode(struct soap *soap, const char *faultsubcodeQName, const char *faultstring, const char *faultdetailXML) +{ return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", faultsubcodeQName, faultstring, faultdetailXML); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +#ifndef WITH_NOSTDLIB +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_print_fault(struct soap *soap, FILE *fd) +{ if (soap_check_state(soap)) + fprintf(fd, "Error: soap struct state not initialized\n"); + else if (soap->error) + { const char *c, *v = NULL, *s, **d; + d = soap_faultcode(soap); + if (!*d) + soap_set_fault(soap); + c = *d; + if (soap->version == 2) + v = *soap_faultsubcode(soap); + s = *soap_faultstring(soap); + d = soap_faultdetail(soap); + fprintf(fd, "%s%d fault: %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, c, v ? v : "no subcode", s ? s : "[no reason]", d && *d ? *d : "[no detail]"); + } +} +#endif +#endif + +/******************************************************************************/ +#ifdef __cplusplus +#ifndef WITH_LEAN +#ifndef WITH_NOSTDLIB +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_stream_fault(struct soap *soap, std::ostream& os) +{ if (soap_check_state(soap)) + os << "Error: soap struct state not initialized\n"; + else if (soap->error) + { const char *c, *v = NULL, *s, **d; + d = soap_faultcode(soap); + if (!*d) + soap_set_fault(soap); + c = *d; + if (soap->version == 2) + v = *soap_faultsubcode(soap); + s = *soap_faultstring(soap); + d = soap_faultdetail(soap); + os << (soap->version ? "SOAP 1." : "Error ") + << (soap->version ? (int)soap->version : soap->error) + << " fault: " << c + << "[" << (v ? v : "no subcode") << "]" + << std::endl + << "\"" << (s ? s : "[no reason]") << "\"" + << std::endl + << "Detail: " << (d && *d ? *d : "[no detail]") + << std::endl; + } +} +#endif +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +#ifndef WITH_NOSTDLIB +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_sprint_fault(struct soap *soap, char *buf, size_t len) +{ if (soap_check_state(soap)) + strncpy(buf, "Error: soap struct not initialized", len); + else if (soap->error) + { const char *c, *v = NULL, *s, **d; + d = soap_faultcode(soap); + if (!*d) + soap_set_fault(soap); + c = *d; + if (soap->version == 2) + v = *soap_faultsubcode(soap); + s = *soap_faultstring(soap); + d = soap_faultdetail(soap); +#ifdef WIN32 + _snprintf +#else + snprintf +#endif + (buf, len, "%s%d fault: %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, c, v ? v : "no subcode", s ? s : "[no reason]", d && *d ? *d : "[no detail]"); + } + return buf; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +#ifndef WITH_NOSTDLIB +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_print_fault_location(struct soap *soap, FILE *fd) +{ +#ifndef WITH_LEAN + int i, j, c1, c2; + if (soap->error && soap->bufidx <= soap->buflen && soap->buflen > 0 && soap->buflen <= SOAP_BUFLEN) + { i = (int)soap->bufidx - 1; + if (i <= 0) + i = 0; + c1 = soap->buf[i]; + soap->buf[i] = '\0'; + if ((int)soap->buflen >= i + 1024) + j = i + 1023; + else + j = (int)soap->buflen - 1; + c2 = soap->buf[j]; + soap->buf[j] = '\0'; + fprintf(fd, "%s%c\n\n", soap->buf, c1); + if (soap->bufidx < soap->buflen) + fprintf(fd, "%s\n", soap->buf + soap->bufidx); + soap->buf[i] = c1; + soap->buf[j] = c2; + } +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_register_plugin_arg(struct soap *soap, int (*fcreate)(struct soap*, struct soap_plugin*, void*), void *arg) +{ register struct soap_plugin *p; + register int r; + if (!(p = (struct soap_plugin*)SOAP_MALLOC(soap, sizeof(struct soap_plugin)))) + return soap->error = SOAP_EOM; + p->id = NULL; + p->data = NULL; + p->fcopy = NULL; + p->fdelete = NULL; + r = fcreate(soap, p, arg); + if (!r && p->fdelete) + { p->next = soap->plugins; + soap->plugins = p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Registered '%s' plugin\n", p->id)); + return SOAP_OK; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not register plugin '%s': plugin returned error %d (or fdelete callback not set)\n", p->id?p->id:"?", r)); + SOAP_FREE(soap, p); + return r; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static void * +fplugin(struct soap *soap, const char *id) +{ register struct soap_plugin *p; + for (p = soap->plugins; p; p = p->next) + if (p->id == id || !strcmp(p->id, id)) + return p->data; + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void * +SOAP_FMAC2 +soap_lookup_plugin(struct soap *soap, const char *id) +{ return soap->fplugin(soap, id); +} +#endif + +/******************************************************************************/ +#ifdef __cplusplus +} +#endif + +/******************************************************************************\ + * + * C++ soap struct methods + * +\******************************************************************************/ + +#ifdef __cplusplus +soap::soap() +{ soap_init(this); +} +#endif + +/******************************************************************************/ +#ifdef __cplusplus +soap::soap(soap_mode m) +{ soap_init1(this, m); +} +#endif + +/******************************************************************************/ +#ifdef __cplusplus +soap::soap(soap_mode im, soap_mode om) +{ soap_init2(this, im, om); +} +#endif + +/******************************************************************************/ +#ifdef __cplusplus +soap::soap(struct soap& soap) +{ soap_copy_context(this, &soap); +} +#endif + +/******************************************************************************/ +#ifdef __cplusplus +soap::~soap() +{ soap_destroy(this); + soap_end(this); + soap_done(this); +} +#endif + +/******************************************************************************/ diff --git a/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.10.h b/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.10.h new file mode 100644 index 0000000..7ca5f12 --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.10.h @@ -0,0 +1,2281 @@ +/* + stdsoap2.h 2.7.10 + + gSOAP runtime engine + +gSOAP XML Web services tools +Copyright (C) 2000-2008, Robert van Engelen, Genivia Inc., All Rights Reserved. +This part of the software is released under ONE of the following licenses: +GPL, the gSOAP public license, OR Genivia's license for commercial use. +-------------------------------------------------------------------------------- +Contributors: + +Wind River Systems, Inc., for the following additions + - vxWorks compatible +-------------------------------------------------------------------------------- +gSOAP public license. + +The contents of this file are subject to the gSOAP Public License Version 1.3 +(the "License"); you may not use this file except in compliance with the +License. You may obtain a copy of the License at +http://www.cs.fsu.edu/~engelen/soaplicense.html +Software distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +for the specific language governing rights and limitations under the License. + +The Initial Developer of the Original Code is Robert A. van Engelen. +Copyright (C) 2000-2008, Robert van Engelen, Genivia Inc., All Rights Reserved. +-------------------------------------------------------------------------------- +GPL license. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA + +Author contact information: +engelen@genivia.com / engelen@acm.org + +This program is released under the GPL with the additional exemption that +compiling, linking, and/or using OpenSSL is allowed. +-------------------------------------------------------------------------------- +A commercial use license is available from Genivia, Inc., contact@genivia.com +-------------------------------------------------------------------------------- +*/ + +#ifdef WITH_SOAPDEFS_H +# include "soapdefs.h" /* include user-defined stuff */ +#endif + +#ifndef _THREAD_SAFE +# define _THREAD_SAFE +#endif + +#ifndef OPENSERVER +# ifndef _REENTRANT +# define _REENTRANT +# endif +#endif + +#ifndef SOAP_FMAC1 /* stdsoap2.h declaration macro */ +# define SOAP_FMAC1 +#endif + +#ifndef SOAP_FMAC2 /* stdsoap2.h declaration macro */ +# define SOAP_FMAC2 +#endif + +#ifndef SOAP_FMAC3 /* (de)serializer declaration macro */ +# define SOAP_FMAC3 +#endif + +#ifndef SOAP_FMAC3S /* string converter for (de)serializer declaration macro */ +# define SOAP_FMAC3S SOAP_FMAC3 +#endif + +#ifndef SOAP_FMAC4 /* (de)serializer declaration macro */ +# define SOAP_FMAC4 +#endif + +#ifndef SOAP_FMAC4S /* string converter for (de)serializer declaration macro */ +# define SOAP_FMAC4S SOAP_FMAC4 +#endif + +#ifndef SOAP_FMAC5 /* stub/skeleton declaration macro */ +# define SOAP_FMAC5 +#endif + +#ifndef SOAP_FMAC6 /* stub/skeleton declaration macro */ +# define SOAP_FMAC6 +#endif + +#ifndef SOAP_CMAC /* class declaration macro */ +# define SOAP_CMAC +#endif + +#ifndef SOAP_NMAC /* namespace table declaration macro */ +# define SOAP_NMAC +#endif + +#ifndef SOAP_SOURCE_STAMP +# define SOAP_SOURCE_STAMP(str) +#endif + +/* gSOAP 2.7.4 and higher: fast look-aside buffering is stable */ +#ifndef WITH_FAST +# define WITH_FAST +#endif + +#ifdef WITH_LEANER +# ifndef WITH_LEAN +# define WITH_LEAN +# endif +#endif + +#ifdef WITH_LEAN +# ifdef WITH_COOKIES +# error "Cannot build WITH_LEAN code WITH_COOKIES enabled" +# endif +#endif + +#ifndef STDSOAP_H +#define STDSOAP_H + +#if defined(__vxworks) || defined(__VXWORKS__) +# define VXWORKS +#endif + +#ifdef _WIN32 +# ifndef WIN32 +# define WIN32 +# endif +#endif + +#ifdef _WIN32_WCE +# ifndef UNDER_CE +# define UNDER_CE _WIN32_WCE +# endif +#endif + +#ifdef UNDER_CE +# ifndef WIN32 +# define WIN32 +# endif +#endif + +#ifdef __BORLANDC__ +# ifdef __WIN32__ +# ifndef WIN32 +# define WIN32 +# endif +# endif +#endif + +#ifdef __CYGWIN__ +# ifndef CYGWIN +# define CYGWIN +# endif +#endif + +#ifdef __SYMBIAN32__ +# define SYMBIAN +# undef WIN32 +#endif + +#if defined(__palmos__) || defined(PALM_GCC) || defined(__PALMOS_TRAPS__) +# ifndef PALM +# define PALM +# endif +#endif + +#if defined(__hpux) +# ifndef HP_UX +# define HP_UX +# endif +#endif + +#if defined(__digital__) && defined(__unix__) +# ifndef TRU64 +# define TRU64 +# endif +#endif + +#ifdef __MVS__ +# ifndef OS390 +# define OS390 +# endif +#endif + +#ifdef HAVE_CONFIG_H +# include "config.h" +# if defined(WITH_OPENSSL) +# ifndef HAVE_OPENSSL_SSL_H +# undef WITH_OPENSSL +# endif +# endif +# if defined(WITH_ZLIB) || defined(WITH_GZIP) +# ifndef HAVE_ZLIB_H +# undef WITH_ZLIB +# undef WITH_GZIP +# endif +# endif +#else +# if defined(UNDER_CE) +# define WITH_NOEMPTYSTRUCT +# define WITH_LEAN +# define HAVE_SSCANF +# elif defined(WIN32) +# define WITH_NOEMPTYSTRUCT +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# define SOAP_LONG_FORMAT "%I64d" +# define SOAP_ULONG_FORMAT "%I64u" +# elif defined(CYGWIN) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(__APPLE__) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOD_L +# define HAVE_SSCANF_L +# define HAVE_SPRINTF_L +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_TIMEGM +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(_AIX43) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(_AIX41) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(HP_UX) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(FREEBSD) || defined(__FreeBSD__) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +//# define HAVE_STRTOD_L +//# define HAVE_SSCANF_L +//# define HAVE_SPRINTF_L +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_STRTOLL +# define HAVE_STRTOULL +# define HAVE_GETTIMEOFDAY +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# define SOAP_LONG_FORMAT "%qd" +# define SOAP_ULONG_FORMAT "%qu" +# elif defined(__VMS) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(__GLIBC__) || defined(__GNU__) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOD_L +# define HAVE_SSCANF_L +# define HAVE_SPRINTF_L +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_STRTOLL +# define HAVE_STRTOULL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_TIMEGM +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# define HAVE_ISNAN +# elif defined(TRU64) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_GETTIMEOFDAY +# define HAVE_SYS_TIMEB_H +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define __USE_STD_IOSTREAM +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# define SOAP_LONG_FORMAT "%ld" +# define SOAP_ULONG_FORMAT "%lu" +# elif defined(MAC_CARBON) +# define WITH_NOIO +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOD_L +# define HAVE_SSCANF_L +# define HAVE_SPRINTF_L +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GETHOSTBYNAME_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(PALM) +# define WITH_LEAN +# define HAVE_STRTOD /* strtod() is defined in palmFunctions.h */ +# include /* Needs to be included before unix headers */ +# include +# define IGNORE_STDIO_STUBS +# include +# define O_NONBLOCK FNONBIO +# include +# include "palmFunctions.h" +# elif defined(SYMBIAN) +# define WITH_LEAN +# define WITH_NONAMESPACES +# define HAVE_STRTOD /* use STRTOD since sscanf doesn't seem to work */ +# include +# include +# elif defined(VXWORKS) +# ifdef _WRS_KERNEL +# define _POSIX_THREADS 1 +# endif +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_GMTIME +# define HAVE_LOCALTIME +# define HAVE_MKTIME +# elif defined(OS390) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(AS400) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(__QNX__) || defined(QNX) +/* QNX does not have a working version of strtof */ +# undef HAVE_STRTOF +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GETHOSTBYNAME_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# define LONG64 long +# define ULONG64 unsigned LONG64 +# define SOAP_LONG_FORMAT "%ld" +# define SOAP_ULONG_FORMAT "%lu" +# else +/* Default asumptions on supported functions */ +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GETHOSTBYNAME_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# endif +#endif + +#if defined(HAVE_XLOCALE_H) || defined(HAVE_STRTOD_L) || defined(HAVE_STRTOF_L) || defined(HAVE_SSCANF_L) || defined(HAVE_SPRINTF_L) +# include +#endif + +#ifndef WITH_NOSTDLIB +# include +# ifndef PALM +# include +# include +# endif +# include +# include +#endif + +#if defined(__cplusplus) && !defined(WITH_LEAN) +# include +# include +#endif + +#ifdef WITH_NOHTTP +# ifndef WITH_NOIO +# define WITH_NOIO +# undef WITH_COOKIES +# endif +#endif + +/* Suggestion when SOAP_FD_EXCEEDED error occurs: + Some systems allow increasing FD_SETSIZE before including sys/types.h: +#define FD_SETSIZE (2048) +*/ + +#ifndef UNDER_CE +# ifndef PALM +# ifndef WITH_NOIO +# include +# include +# endif +# ifndef WITH_LEAN +# ifdef HAVE_SYS_TIMEB_H +# include /* for ftime() */ +# endif +# include +# endif +# endif +#endif + +#ifdef OPENSERVER +# include +# include +# include + extern int h_errno; +#endif + +#ifndef WITH_NOIO +# ifndef WIN32 +# ifndef PALM +# include +# ifdef VXWORKS +# include +# include +# ifndef _WRS_KERNEL +# include +# endif +# else +# ifndef SYMBIAN +# include +# endif +# endif +# ifdef SUN_OS +# include /* SUN */ +# include /* SUN < 2.8 (?) */ +# endif +# ifdef VXWORKS +# ifdef _WRS_KERNEL +# include +# endif +# else +# include +# endif +# include +# ifdef OS390 +# include +# else +# include /* TCP_NODELAY */ +# endif +# include +# endif +# endif +#endif + +#ifdef WIN32 +# define SOAP_WINSOCKINT int +#else +# define SOAP_WINSOCKINT size_t +#endif + +#ifdef WIN32 +# ifndef UNDER_CE +# include +# include +# endif +# ifdef WITH_IPV6 +# include /* Visual Studio 2005 users: you must install the Platform SDK (R2) */ +# include +# include +# define SOAP_GAI_STRERROR gai_strerrorA +# else +# include /* Visual Studio 2005 users: you must install the Platform SDK (R2) */ +/* # include */ /* Alternative: use winsock2 (not available with eVC) */ +# endif +#else +# ifdef VXWORKS +# include +# include +# include +# endif +# ifndef WITH_NOIO +# ifndef PALM +# include +# include +# include +# include +# ifdef _AIX41 +# include +# endif +# endif +# endif +#endif + +#ifdef WITH_FASTCGI +# include +#endif + +#ifdef WITH_OPENSSL +# define OPENSSL_NO_KRB5 +# include +# include +# include +# include +# include +# ifndef ALLOW_OLD_VERSIONS +# if (OPENSSL_VERSION_NUMBER < 0x00905100L) +# error "Must use OpenSSL 0.9.6 or later" +# endif +# endif +#endif + +#ifdef WITH_GZIP +# ifndef WITH_ZLIB +# define WITH_ZLIB +# endif +#endif + +#ifdef WITH_CASEINSENSITIVETAGS +# define SOAP_STRCMP soap_tag_cmp /* case insensitve XML element/attribute names */ +#else +# define SOAP_STRCMP strcmp /* case sensitive XML element/attribute names */ +#endif + +#ifdef WITH_ZLIB +# include +#endif + +#ifndef WITH_NOSTDLIB +# ifndef PALM +# include /* for isnan() */ +# endif +#endif + +/* #define DEBUG */ /* Uncomment to debug sending (in file SENT.log) receiving (in file RECV.log) and messages (in file TEST.log) */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Portability: define SOAP_SOCKLEN_T */ +#if defined(_AIX) +# if defined(_AIX43) +# define SOAP_SOCKLEN_T socklen_t +# else +# define SOAP_SOCKLEN_T int +# endif +#elif defined(SOCKLEN_T) +# define SOAP_SOCKLEN_T SOCKLEN_T +#elif defined(__socklen_t_defined) || defined(_SOCKLEN_T) || defined(CYGWIN) || defined(FREEBSD) || defined(__FreeBSD__) || defined(__QNX__) || defined(QNX) +# define SOAP_SOCKLEN_T socklen_t +#elif defined(IRIX) || defined(WIN32) || defined(__APPLE__) || defined(HP_UX) || defined(SUN_OS) || defined(OPENSERVER) || defined(TRU64) || defined(VXWORKS) +# define SOAP_SOCKLEN_T int +#else +# define SOAP_SOCKLEN_T size_t +#endif + +#ifndef SOAP_SOCKET +# ifdef WIN32 +# define SOAP_SOCKET SOCKET +# define soap_closesocket(n) closesocket(n) +# else +# define SOAP_SOCKET int +# define soap_closesocket(n) close(n) +# endif +#endif + +#define SOAP_INVALID_SOCKET ((SOAP_SOCKET)-1) +#define soap_valid_socket(n) ((n) != SOAP_INVALID_SOCKET) + +#ifndef SOAP_GAI_STRERROR +# define SOAP_GAI_STRERROR gai_strerror +#endif + +#ifndef FD_SETSIZE +# define FD_SETSIZE (1024) +#endif + +#if defined(SYMBIAN) +# define LONG64 long +# define ULONG64 unsigned LONG64 +#elif !defined(WIN32) || defined(CYGWIN) || defined(__GLIBC__) || defined(__GNU__) +# ifndef LONG64 +# if defined(__GLIBC__) +# include +# if (__WORDSIZE == 64) +# define LONG64 int64_t +# define ULONG64 uint64_t +# ifndef SOAP_LONG_FORMAT +# define SOAP_LONG_FORMAT "%ld" +# endif +# ifndef SOAP_ULONG_FORMAT +# define SOAP_ULONG_FORMAT "%lu" +# endif +# else +# define LONG64 long long +# define ULONG64 unsigned LONG64 +# endif +# else +# define LONG64 long long +# define ULONG64 unsigned LONG64 +# endif +# endif +#elif defined(UNDER_CE) +# define LONG64 __int64 +# define ULONG64 unsigned LONG64 +#elif defined(__BORLANDC__) +# define LONG64 __int64 +# define ULONG64 unsigned LONG64 +#endif + +#ifndef SOAP_LONG_FORMAT +# define SOAP_LONG_FORMAT "%lld" /* printf format for 64 bit ints */ +#endif + +#ifndef SOAP_ULONG_FORMAT +# define SOAP_ULONG_FORMAT "%llu" /* printf format for unsigned 64 bit ints */ +#endif + +#if defined(WIN32) && !defined(CYGWIN) +# define soap_int32 __int32 +#elif defined(SYMBIAN) +# define soap_int32 long +#elif defined(PALM) +# define soap_int32 Int32 +#elif defined(_AIX) +# if defined(_AIX43) +# define soap_int32 int32_t +# else +# define soap_int32 signed int +# endif +#else +# define soap_int32 int32_t +#endif + +#ifdef WIN32 +# define SOAP_ERANGE ERANGE +# define SOAP_EINTR WSAEINTR +# define SOAP_EAGAIN WSAEWOULDBLOCK +# define SOAP_EWOULDBLOCK WSAEWOULDBLOCK +# define SOAP_EINPROGRESS WSAEINPROGRESS +# define SOAP_EADDRINUSE WSAEADDRINUSE +#else +# define SOAP_ERANGE ERANGE +# define SOAP_EINTR EINTR +# define SOAP_EAGAIN EAGAIN +# define SOAP_EADDRINUSE EADDRINUSE +# ifdef SYMBIAN +# define SOAP_EWOULDBLOCK 9898 +# define SOAP_EINPROGRESS 9899 +# else +# define SOAP_EWOULDBLOCK EWOULDBLOCK +# define SOAP_EINPROGRESS EINPROGRESS +# endif +#endif + +#ifdef WIN32 +# ifdef UNDER_CE +# define soap_errno GetLastError() +# define soap_socket_errno(s) GetLastError() +# define soap_reset_errno SetLastError(0) +# else +# define soap_errno GetLastError() +# define soap_socket_errno(s) WSAGetLastError() +# define soap_reset_errno SetLastError(0) +# endif +#else +# ifndef WITH_NOIO +# define soap_errno errno +# define soap_socket_errno(s) errno +# define soap_reset_errno (errno = 0) +# else +# define soap_errno 0 +# define soap_socket_errno(s) 0 +# define soap_reset_errno +# endif +#endif + +#ifndef SOAP_BUFLEN +# ifndef WITH_LEAN +# define SOAP_BUFLEN (65536) /* buffer length for socket packets, also used by gethostbyname_r and UDP messages, so don't make this too small */ +# else +# define SOAP_BUFLEN (2048) +# endif +#endif +#ifndef SOAP_LABLEN +# define SOAP_LABLEN (256) /* initial look-aside buffer length */ +#endif +#ifndef SOAP_PTRBLK +# define SOAP_PTRBLK (32) /* block allocation for pointer hash table chains */ +#endif +#ifndef SOAP_PTRHASH +# ifndef WITH_LEAN +# define SOAP_PTRHASH (1024) /* size of pointer analysis hash table (must be power of 2) */ +# else +# define SOAP_PTRHASH (32) +# endif +#endif +#ifndef SOAP_IDHASH +# ifndef WITH_LEAN +# define SOAP_IDHASH (1999) /* prime size of hash table for parsed id/ref */ +# else +# define SOAP_IDHASH (19) /* 19, 199 */ +# endif +#endif +#ifndef SOAP_BLKLEN +# ifndef WITH_LEAN +# define SOAP_BLKLEN (256) /* size of blocks to collect long strings and XML attributes */ +# else +# define SOAP_BLKLEN (32) +# endif +#endif +#ifndef SOAP_TAGLEN +# ifndef WITH_LEAN +# define SOAP_TAGLEN (1024) /* maximum length of XML element tag/attribute name or host/path name + 1 */ +# else +# define SOAP_TAGLEN (64) +# endif +#endif +#ifndef SOAP_HDRLEN +# ifndef WITH_LEAN +# define SOAP_HDRLEN (8192) /* maximum length of HTTP header line (must be >4096 to read cookies) */ +# else +# define SOAP_HDRLEN (1024) +# endif +#endif +#ifndef SOAP_MAXDIMS +# ifndef WITH_LEAN +# define SOAP_MAXDIMS (16) /* maximum array dimensions (array nestings) must be less than 64 to protect soap->tmpbuf */ +# else +# define SOAP_MAXDIMS (4) +# endif +#endif + +#ifndef SOAP_MAXLOGS +# define SOAP_MAXLOGS (3) /* max number of debug logs per struct soap environment */ +# define SOAP_INDEX_RECV (0) +# define SOAP_INDEX_SENT (1) +# define SOAP_INDEX_TEST (2) +#endif + +#ifndef SOAP_MAXKEEPALIVE +# define SOAP_MAXKEEPALIVE (100) /* max iterations to keep server connection alive */ +#endif + +#ifndef SOAP_MAXARRAYSIZE +# define SOAP_MAXARRAYSIZE (100000) /* "trusted" max size of inbound SOAP array for compound array allocation */ +#endif + +#ifdef VXWORKS +# ifdef __INCmathh +# include +# ifndef HAVE_ISNAN +# define HAVE_ISNAN +# endif +# define soap_isnan(num) isNan(num) +# endif +#endif + +#ifdef WIN32 +# include +# ifndef HAVE_ISNAN +# define HAVE_ISNAN +# endif +# define soap_isnan(num) _isnan(num) +#endif + +#ifdef SUN_OS +# define HAVE_ISNAN +#endif + +#ifdef __APPLE__ +# ifdef __cplusplus +# ifndef isnan +extern "C" int isnan(double); +# endif +# endif +# define HAVE_ISNAN +#endif + +#if !defined(HAVE_ISNAN) && (defined(_MATH_H) || defined(_MATH_INCLUDED)) +# define HAVE_ISNAN +#endif + +extern const struct soap_double_nan { unsigned int n1, n2; } soap_double_nan; + +#ifdef VXWORKS +# ifndef FLT_MAX +# define FLT_MAX _ARCH_FLT_MAX +# endif +# ifndef DBL_MAX +# define DBL_MAX _ARCH_DBL_MAX +# endif +#endif + +#ifndef FLT_NAN +# define FLT_NAN (*(float*)(void*)&soap_double_nan) +#endif + +#ifndef FLT_PINFTY +# if defined(FLT_MAX) +# define FLT_PINFTY FLT_MAX +# elif defined(HUGE_VALF) +# define FLT_PINFTY (float)HUGE_VALF +# elif defined(HUGE_VAL) +# define FLT_PINFTY (float)HUGE_VAL +# elif defined(FLOAT_MAX) +# define FLT_PINFTY FLOAT_MAX +# else +# define FLT_PINFTY (3.40282347e+38F) +# endif +#endif + +#ifndef FLT_NINFTY +# define FLT_NINFTY (-FLT_PINFTY) +#endif + +#ifndef DBL_NAN +# define DBL_NAN (*(double*)(void*)&soap_double_nan) +#endif + +#ifndef DBL_PINFTY +# if defined(DBL_MAX) +# define DBL_PINFTY DBL_MAX +# elif defined(HUGE_VALF) +# define DBL_PINFTY (double)HUGE_VALF +# elif defined(HUGE_VAL) +# define DBL_PINFTY (double)HUGE_VAL +# elif defined(DOUBLE_MAX) +# define DBL_PINFTY DOUBLE_MAX +# else +# define DBL_PINFTY (1.7976931348623157e+308) +# endif +#endif + +#ifndef DBL_NINFTY +# define DBL_NINFTY (-DBL_PINFTY) +#endif + +#ifndef soap_isnan +# ifdef HAVE_ISNAN +# define soap_isnan(n) isnan(n) +# else +# define soap_isnan(n) (0) +# endif +#endif + +#define soap_ispinfd(n) ((n) >= DBL_PINFTY) +#define soap_ispinff(n) ((n) >= FLT_PINFTY) +#define soap_isninfd(n) ((n) <= DBL_NINFTY) +#define soap_isninff(n) ((n) <= FLT_NINFTY) + +/* gSOAP error codes */ + +#define SOAP_EOF EOF +#define SOAP_ERR EOF +#define SOAP_OK 0 +#define SOAP_CLI_FAULT 1 +#define SOAP_SVR_FAULT 2 +#define SOAP_TAG_MISMATCH 3 +#define SOAP_TYPE 4 +#define SOAP_SYNTAX_ERROR 5 +#define SOAP_NO_TAG 6 +#define SOAP_IOB 7 +#define SOAP_MUSTUNDERSTAND 8 +#define SOAP_NAMESPACE 9 +#define SOAP_USER_ERROR 10 +#define SOAP_FATAL_ERROR 11 +#define SOAP_FAULT 12 +#define SOAP_NO_METHOD 13 +#define SOAP_NO_DATA 14 +#define SOAP_GET_METHOD 15 +#define SOAP_PUT_METHOD 16 +#define SOAP_DEL_METHOD 17 +#define SOAP_HEAD_METHOD 18 +#define SOAP_HTTP_METHOD 19 +#define SOAP_EOM 20 +#define SOAP_MOE 21 +#define SOAP_HDR 22 +#define SOAP_NULL 23 +#define SOAP_DUPLICATE_ID 24 +#define SOAP_MISSING_ID 25 +#define SOAP_HREF 26 +#define SOAP_UDP_ERROR 27 +#define SOAP_TCP_ERROR 28 +#define SOAP_HTTP_ERROR 29 +#define SOAP_SSL_ERROR 30 +#define SOAP_ZLIB_ERROR 31 +#define SOAP_DIME_ERROR 32 +#define SOAP_DIME_HREF 33 +#define SOAP_DIME_MISMATCH 34 +#define SOAP_DIME_END 35 +#define SOAP_MIME_ERROR 36 +#define SOAP_MIME_HREF 37 +#define SOAP_MIME_END 38 +#define SOAP_VERSIONMISMATCH 39 +#define SOAP_PLUGIN_ERROR 40 +#define SOAP_DATAENCODINGUNKNOWN 41 +#define SOAP_REQUIRED 42 +#define SOAP_PROHIBITED 43 +#define SOAP_OCCURS 44 +#define SOAP_LENGTH 45 +#define SOAP_FD_EXCEEDED 46 + +#define soap_xml_error_check(e) ((e) == SOAP_TAG_MISMATCH || (e) == SOAP_NO_TAG || (e) == SOAP_SYNTAX_ERROR || (e) == SOAP_NAMESPACE || (e) == SOAP_DUPLICATE_ID || (e) == SOAP_MISSING_ID || (e) == SOAP_REQUIRED || (e) == SOAP_PROHIBITED || (e) == SOAP_OCCURS || (e) == SOAP_LENGTH || (e) == SOAP_NULL || (e) == SOAP_HREF) +#define soap_soap_error_check(e) ((e) == SOAP_CLI_FAULT || (e) == SOAP_SVR_FAULT || (e) == SOAP_VERSIONMISMATCH || (e) == SOAP_MUSTUNDERSTAND || (e) == SOAP_FAULT || (e) == SOAP_NO_METHOD) +#define soap_tcp_error_check(e) ((e) == SOAP_EOF || (e) == SOAP_TCP_ERROR) +#define soap_ssl_error_check(e) ((e) == SOAP_SSL_ERROR) +#define soap_zlib_error_check(e) ((e) == SOAP_ZLIB_ERROR) +#define soap_http_error_check(e) ((e) == SOAP_HTTP_ERROR || ((e) >= SOAP_GET_METHOD && (e) <= SOAP_HTTP_METHOD)|| (e) == SOAP_NO_DATA || ((e) >= 100 && (e) < 600)) + +/* gSOAP HTTP response status codes 100 to 599 are reserved */ + +/* Codes 600 to 999 are user definable */ + +/* Exceptional gSOAP HTTP response status codes >= 1000 */ + +#define SOAP_STOP 1000 /* No HTTP response */ +#define SOAP_FORM 1001 /* Form request/response */ +#define SOAP_HTML 1002 /* Custom HTML response */ +#define SOAP_FILE 1003 /* Custom file-based response */ + +/* gSOAP HTTP method codes */ + +#define SOAP_POST 2000 +#define SOAP_GET 2001 + +/* gSOAP DIME */ + +#define SOAP_DIME_CF 0x01 +#define SOAP_DIME_ME 0x02 +#define SOAP_DIME_MB 0x04 +#define SOAP_DIME_VERSION 0x08 /* DIME version 1 */ +#define SOAP_DIME_MEDIA 0x10 +#define SOAP_DIME_ABSURI 0x20 + +/* gSOAP ZLIB */ + +#define SOAP_ZLIB_NONE 0x00 +#define SOAP_ZLIB_DEFLATE 0x01 +#define SOAP_ZLIB_INFLATE 0x02 +#define SOAP_ZLIB_GZIP 0x02 + +/* gSOAP transport, connection, and content encoding modes */ + +typedef soap_int32 soap_mode; + +#define SOAP_IO 0x00000003 /* IO mask */ +#define SOAP_IO_FLUSH 0x00000000 /* flush output immediately, no buffering */ +#define SOAP_IO_BUFFER 0x00000001 /* buffer output in packets of size SOAP_BUFLEN */ +#define SOAP_IO_STORE 0x00000002 /* store entire output to determine length for transport */ +#define SOAP_IO_CHUNK 0x00000003 /* use HTTP chunked transfer AND buffer packets */ + +#define SOAP_IO_UDP 0x00000004 /* TCP or UDP */ + +#define SOAP_IO_LENGTH 0x00000008 /* calc message length (internal) */ +#define SOAP_IO_KEEPALIVE 0x00000010 /* keep connection alive */ + +#define SOAP_ENC_LATIN 0x00000020 /* accept iso-8859-1 encoding */ +#define SOAP_ENC_XML 0x00000040 /* plain XML encoding, no HTTP header */ +#define SOAP_ENC_DIME 0x00000080 +#define SOAP_ENC_MIME 0x00000100 +#define SOAP_ENC_MTOM 0x00000200 +#define SOAP_ENC_ZLIB 0x00000400 +#define SOAP_ENC_SSL 0x00000800 + +#define SOAP_ENC 0x00000FFF /* IO and ENC mask */ + +#define SOAP_XML_STRICT 0x00001000 /* apply strict validation */ +#define SOAP_XML_INDENT 0x00002000 /* emit indented XML */ +#define SOAP_XML_CANONICAL 0x00004000 /* EXC C14N canonical XML */ +#define SOAP_XML_TREE 0x00008000 /* emit XML tree (no id/ref) */ +#define SOAP_XML_GRAPH 0x00010000 +#define SOAP_XML_NIL 0x00020000 +#define SOAP_XML_DOM 0x00040000 +#define SOAP_XML_SEC 0x00080000 /* reserved for WS security */ + +#define SOAP_C_NOIOB 0x00100000 /* don't fault on array index out of bounds (just ignore) */ +#define SOAP_C_UTFSTRING 0x00200000 /* (de)serialize strings with UTF8 content */ +#define SOAP_C_MBSTRING 0x00400000 /* (de)serialize strings with multi-byte content */ +#define SOAP_C_NILSTRING 0x00800000 /* serialize empty strings as nil (omitted) */ + +#define SOAP_DOM_TREE 0x01000000 +#define SOAP_DOM_NODE 0x02000000 +#define SOAP_DOM_ASIS 0x04000000 + +#define SOAP_MIME_POSTCHECK 0x10000000 /* MIME flag (internal) */ + +#define SOAP_IO_DEFAULT SOAP_IO_FLUSH + +/* SSL client/server authentication settings */ + +#define SOAP_SSL_NO_AUTHENTICATION 0x00 /* for testing purposes */ +#define SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION 0x01 /* client requires server to authenticate */ +#define SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION 0x02 /* server requires client to authenticate */ +#define SOAP_SSL_SKIP_HOST_CHECK 0x04 /* client does not check the common name of the host in certificate */ +#define SOAP_SSL_RSA 0x08 /* use RSA */ +#define SOAP_SSLv3_TLSv1 0x00 /* SSL v3 and TLS v1 support by default */ +#define SOAP_SSLv3 0x10 /* SSL v3 only */ +#define SOAP_TLSv1 0x20 /* TLS v1 only */ + +#define SOAP_SSL_DEFAULT (SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION | SOAP_SSLv3_TLSv1) + +/* state */ + +#define SOAP_INIT 1 +#define SOAP_COPY 2 + +#define soap_check_state(soap) (!(soap) || ((soap)->state != SOAP_INIT && (soap)->state != SOAP_COPY)) + +/* part */ + +#define SOAP_BEGIN 0 +#define SOAP_IN_ENVELOPE 2 +#define SOAP_IN_HEADER 3 +#define SOAP_END_HEADER 4 +#define SOAP_NO_BODY 5 +#define SOAP_IN_BODY 6 +#define SOAP_END_BODY 7 +#define SOAP_END_ENVELOPE 8 +#define SOAP_END 9 +#define SOAP_BEGIN_SECURITY 10 +#define SOAP_IN_SECURITY 11 +#define SOAP_END_SECURITY 12 + +/* DEBUG macros */ + +#ifndef WITH_LEAN +# ifdef DEBUG +# ifndef SOAP_DEBUG +# define SOAP_DEBUG +# endif +# ifndef SOAP_MEM_DEBUG +# define SOAP_MEM_DEBUG +# endif +# endif +#endif + +#ifdef SOAP_MEM_DEBUG +# ifndef SOAP_MALLOC +# define SOAP_MALLOC(soap, size) soap_track_malloc(soap, __FILE__, __LINE__, size) +# endif +# ifndef SOAP_FREE +# define SOAP_FREE(soap, ptr) soap_track_free(soap, __FILE__, __LINE__, ptr) +# endif +#endif + +#ifndef SOAP_MALLOC /* use libc malloc */ +# define SOAP_MALLOC(soap, size) malloc(size) +#endif + +#ifndef SOAP_FREE /* use libc free */ +# define SOAP_FREE(soap, ptr) free(ptr) +#endif + +#ifdef SOAP_DEBUG +# ifndef SOAP_MESSAGE +# define SOAP_MESSAGE fprintf +# endif +# ifndef DBGLOG +# define DBGLOG(DBGFILE, CMD) \ +{ if (soap)\ + { if (!soap->fdebug[SOAP_INDEX_##DBGFILE])\ + soap_open_logfile((struct soap*)soap, SOAP_INDEX_##DBGFILE);\ + if (soap->fdebug[SOAP_INDEX_##DBGFILE])\ + { FILE *fdebug = soap->fdebug[SOAP_INDEX_##DBGFILE];\ + CMD;\ + fflush(fdebug);\ + }\ + }\ +} +# endif +# ifndef DBGMSG +# define DBGMSG(DBGFILE, MSG, LEN) \ +{ if (soap)\ + { if (!soap->fdebug[SOAP_INDEX_##DBGFILE])\ + soap_open_logfile((struct soap*)soap, SOAP_INDEX_##DBGFILE);\ + if (soap->fdebug[SOAP_INDEX_##DBGFILE])\ + { fwrite((MSG), 1, (LEN), soap->fdebug[SOAP_INDEX_##DBGFILE]);\ + fflush(soap->fdebug[SOAP_INDEX_##DBGFILE]);\ + }\ + }\ +} +# endif +# ifndef DGBFUN +# define DBGFUN(FNAME) DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): %s()\n", __FILE__, __LINE__, FNAME)) +# define DBGFUN1(FNAME, FMT, ARG) DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): %s("FMT")\n", __FILE__, __LINE__, FNAME, (ARG))) +# define DBGFUN2(FNAME, FMT1, ARG1, FMT2, ARG2) DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): %s("FMT1", "FMT2")\n", __FILE__, __LINE__, FNAME, (ARG1), (ARG2))) +# define DBGFUN3(FNAME, FMT1, ARG1, FMT2, ARG2, FMT3, ARG3) DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): %s("FMT1", "FMT2", "FMT3")\n", __FILE__, __LINE__, FNAME, (ARG1), (ARG2), (ARG3))) +# endif +# ifndef DBGHEX +# define DBGHEX(DBGFILE, MSG, LEN) \ +{ if (soap)\ + { if (!soap->fdebug[SOAP_INDEX_##DBGFILE])\ + soap_open_logfile(soap, SOAP_INDEX_##DBGFILE);\ + if (soap->fdebug[SOAP_INDEX_##DBGFILE])\ + { int i; char *s;\ + for (s = (char*)(MSG), i = (LEN); i; i--)\ + fprintf(soap->fdebug[SOAP_INDEX_##DBGFILE], "%2.2X ", (int)*s++&0xFF);\ + fflush(soap->fdebug[SOAP_INDEX_##DBGFILE]);\ + }\ + }\ +} +# endif +#else +# define DBGLOG(DBGFILE, CMD) +# define DBGMSG(DBGFILE, MSG, LEN) +# define DBGFUN(FNAME) +# define DBGFUN1(FNAME, FMT, ARG) +# define DBGFUN2(FNAME, FMT1, ARG1, FMT2, ARG2) +# define DBGFUN3(FNAME, FMT1, ARG1, FMT2, ARG2, FMT3, ARG3) +# define DBGHEX(DBGFILE, MSG, LEN) +#endif + +/* UCS-4 requires 32 bits (0-7FFFFFFF, the sign bit is used by gSOAP to distinguish XML entities) */ +typedef soap_int32 soap_wchar; + +/* namespace table row */ +struct Namespace +{ const char *id; + const char *ns; + const char *in; + char *out; +}; + +/* namespace stack */ +struct soap_nlist +{ struct soap_nlist *next; + unsigned int level; /* nesting depth level */ + short index; /* corresponding entry in ns mapping table */ + char *ns; /* only set when parsed ns URI is not in the ns mapping table */ + char id[1]; /* the actual string value flows into the allocated region below this struct */ +}; + +/* block stack for nested block allocations */ +struct soap_blist +{ struct soap_blist *next; + char *ptr; + size_t size; +}; + +/* array layout */ +struct soap_array +{ void *__ptr; + int __size; +}; + +/* pointer serialization management */ +struct soap_plist +{ struct soap_plist *next; + const void *ptr; + const struct soap_array *array; + int type; + int id; + char mark1; + char mark2; +}; + +/* block allocation for pointer serialization management */ +struct soap_pblk +{ struct soap_pblk *next; + struct soap_plist plist[SOAP_PTRBLK]; +}; + +#ifdef SOAP_MEM_DEBUG +/* malloc/free tracking for debugging */ +struct soap_mlist +{ struct soap_mlist *next; + const void *ptr; + const char *file; + int line; + short live; +}; +#endif + +/* class allocation list */ +struct soap_clist +{ struct soap_clist *next; + void *ptr; + int type; + int size; + int (*fdelete)(struct soap_clist*); +}; + +/* attributes */ +struct soap_attribute +{ struct soap_attribute *next; + char *value; + size_t size; + char *ns; + short visible; + char name[1]; /* the actual name string flows into the allocated region below this struct */ +}; + +#ifndef WITH_LEAN +struct soap_cookie +{ struct soap_cookie *next; + char *name; + char *value; + char *domain; + char *path; + time_t expire; /* client-side: local time to expire */ + long maxage; /* server-side: seconds to expire */ + unsigned int version; + short secure; + short session; /* server-side */ + short env; /* server-side: got cookie from client and should not be (re)send */ + short modified; /* server-side: client cookie was modified and should be send */ +}; +#endif + +#ifdef __cplusplus +SOAP_FMAC1 struct soap_multipart* SOAP_FMAC2 soap_next_multipart(struct soap_multipart*); + +class soap_multipart_iterator +{ public: + struct soap_multipart *content; + bool operator==(const soap_multipart_iterator& iter) const + { return content == iter.content; } + bool operator!=(const soap_multipart_iterator& iter) const + { return content != iter.content; } + struct soap_multipart &operator*() const + { return *content; } + soap_multipart_iterator &operator++() + { content = soap_next_multipart(content); return *this; } + soap_multipart_iterator() : content(NULL) + { } + soap_multipart_iterator(struct soap_multipart *p) : content(p) + { } +}; +#endif + +#ifndef WITH_LEANER +struct soap_dime +{ size_t count; + size_t size; + size_t chunksize; + size_t buflen; + char flags; + char *ptr; + const char *id; + const char *type; + const char *options; + struct soap_multipart *list; /* list of DIME attachments received */ + struct soap_multipart *first, *last; /* temporary in/out queue */ +#ifdef __cplusplus + soap_multipart_iterator begin() + { soap_multipart_iterator iter(list); return iter; }; + soap_multipart_iterator end() + { soap_multipart_iterator iter(NULL); return iter; }; +#endif +}; +#endif + +#ifndef WITH_LEANER +struct soap_mime +{ char *boundary; /* MIME boundary */ + const char *start; /* MIME start ID */ + struct soap_multipart *list; /* list of MIME attachments received */ + struct soap_multipart *first, *last; /* temporary in/out queue */ +#ifdef __cplusplus + soap_multipart_iterator begin() + { soap_multipart_iterator iter(list); return iter; }; + soap_multipart_iterator end() + { soap_multipart_iterator iter(NULL); return iter; }; +#endif +}; +#endif + +#ifndef WITH_LEANER +/* RFC2045 MIME content transfer encodings */ +enum soap_mime_encoding +{ SOAP_MIME_NONE, + SOAP_MIME_7BIT, + SOAP_MIME_8BIT, + SOAP_MIME_BINARY, + SOAP_MIME_QUOTED_PRINTABLE, + SOAP_MIME_BASE64, + SOAP_MIME_IETF_TOKEN, + SOAP_MIME_X_TOKEN +}; +#endif + +#ifndef WITH_LEANER +/* DIME/MIME multipart list */ +struct soap_multipart +{ struct soap_multipart *next; + char *ptr; /* points to raw data content */ + size_t size; /* size of data content */ + const char *id; /* DIME/MIME content ID or form data name */ + const char *type; /* DIME/MIME type (MIME type format) */ + const char *options; /* DIME options */ + enum soap_mime_encoding encoding; /* MIME Content-Transfer-Encoding */ + const char *location; /* MIME Content-Location (optional) */ + const char *description; /* MIME Content-Description (optional) */ +#ifdef __cplusplus + typedef soap_multipart_iterator iterator; +#endif +}; +#endif + +#ifndef WITH_LEANER +/* attachment DIME and MTOM XOP forwarding */ +struct soap_xlist +{ struct soap_xlist *next; + unsigned char **ptr; + int *size; + char *id; + char **type; + char **options; +}; +#endif + +/******************************************************************************/ + +#ifndef WITH_LEANER +#ifdef __cplusplus +class soap_dom_attribute_iterator +{ public: + struct soap_dom_attribute *att; + const char *nstr; + const char *name; + bool operator==(const soap_dom_attribute_iterator&) const; + bool operator!=(const soap_dom_attribute_iterator&) const; + struct soap_dom_attribute &operator*() const; + soap_dom_attribute_iterator &operator++(); + soap_dom_attribute_iterator(); + soap_dom_attribute_iterator(struct soap_dom_attribute*); + ~soap_dom_attribute_iterator(); +}; +#endif +#endif + +#ifndef WITH_LEANER +struct soap_dom_attribute +{ struct soap_dom_attribute *next; + const char *nstr; + char *name; + char *data; + wchar_t *wide; + struct soap *soap; +#ifdef __cplusplus + typedef soap_dom_attribute_iterator iterator; + struct soap_dom_attribute &set(const char *nstr, const char *name); /* set namespace and name */ + struct soap_dom_attribute &set(const char *data); /* set data */ + soap_dom_attribute_iterator begin(); + soap_dom_attribute_iterator end(); + soap_dom_attribute_iterator find(const char *nstr, const char *name); + void unlink(); + soap_dom_attribute(); + soap_dom_attribute(struct soap *soap); + soap_dom_attribute(struct soap *soap, const char *nstr, const char *name, const char *data); + ~soap_dom_attribute(); +#endif +}; +#endif + +#ifndef WITH_LEANER +#ifdef __cplusplus +class soap_dom_element_iterator +{ public: + struct soap_dom_element *elt; + const char *nstr; + const char *name; + int type; + bool operator==(const soap_dom_element_iterator&) const; + bool operator!=(const soap_dom_element_iterator&) const; + struct soap_dom_element &operator*() const; + soap_dom_element_iterator &operator++(); + soap_dom_element_iterator(); + soap_dom_element_iterator(struct soap_dom_element*); + ~soap_dom_element_iterator(); +}; +#endif +#endif + +#ifndef WITH_LEANER +struct soap_dom_element +{ struct soap_dom_element *next; /* next sibling */ + struct soap_dom_element *prnt; /* parent */ + struct soap_dom_element *elts; /* list of child elements */ + struct soap_dom_attribute *atts; /* list of attributes */ + const char *nstr; /* namespace string */ + char *name; /* element tag name */ + char *data; /* element content data (with SOAP_C_UTFSTRING flag set) */ + wchar_t *wide; /* element content data */ + int type; /* optional: serialized C/C++ data type */ + void *node; /* optional: pointer to serialized C/C++ data */ + char *head; /* leading whitespace to start tag */ + char *tail; /* leading whitespace to end tag */ + struct soap *soap; /* soap context that manages this node */ +#ifdef __cplusplus + typedef soap_dom_element_iterator iterator; + struct soap_dom_element &set(const char *nstr, const char *name); + struct soap_dom_element &set(const char *data); + struct soap_dom_element &set(void *node, int type); + struct soap_dom_element &add(struct soap_dom_element*); + struct soap_dom_element &add(struct soap_dom_element&); + struct soap_dom_element &add(struct soap_dom_attribute*); + struct soap_dom_element &add(struct soap_dom_attribute&); + soap_dom_element_iterator begin(); + soap_dom_element_iterator end(); + soap_dom_element_iterator find(const char *nstr, const char *name); + soap_dom_element_iterator find(int type); + void unlink(); + soap_dom_element(); + soap_dom_element(struct soap *soap); + soap_dom_element(struct soap *soap, const char *nstr, const char *name); + soap_dom_element(struct soap *soap, const char *nstr, const char *name, const char *data); + soap_dom_element(struct soap *soap, const char *nstr, const char *name, void *node, int type); + ~soap_dom_element(); +#endif +}; +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_dom_next_element(struct soap_dom_element *elt); +SOAP_FMAC1 struct soap_dom_attribute * SOAP_FMAC2 soap_dom_next_attribute(struct soap_dom_attribute *att); +#endif + +#if defined(__cplusplus) && !defined(WITH_LEAN) +} +extern std::ostream &operator<<(std::ostream&, const struct soap_dom_element&); +extern std::istream &operator>>(std::istream&, struct soap_dom_element&); +extern "C" { +#endif + +/******************************************************************************/ + +#ifdef WIN32 +# ifdef SOAP_STD_EXPORTS +# define SOAP_STD_API __declspec(dllexport) +# else +# define SOAP_STD_API +# endif +#else +# define SOAP_STD_API +#endif + +struct SOAP_STD_API soap +{ short state; /* 0 = uninitialized, 1 = initialized, 2 = copy of another soap struct */ + short version; /* 1 = SOAP1.1 and 2 = SOAP1.2 (set automatically from namespace URI in nsmap table) */ + soap_mode mode; + soap_mode imode; + soap_mode omode; + const char *float_format; /* user-definable format string for floats (<1024 chars) */ + const char *double_format; /* user-definable format string for doubles (<1024 chars) */ + const char *dime_id_format; /* user-definable format string for integer DIME id ( 0, gives socket recv timeout in seconds, < 0 in usec */ + int send_timeout; /* when > 0, gives socket send timeout in seconds, < 0 in usec */ + int connect_timeout; /* when > 0, gives socket connect() timeout in seconds, < 0 in usec */ + int accept_timeout; /* when > 0, gives socket accept() timeout in seconds, < 0 in usec */ + int socket_flags; /* socket recv() and send() flags, e.g. set to MSG_NOSIGNAL to disable sigpipe */ + int connect_flags; /* connect() SOL_SOCKET sockopt flags, e.g. set to SO_DEBUG to debug socket */ + int bind_flags; /* bind() SOL_SOCKET sockopt flags, e.g. set to SO_REUSEADDR to enable reuse */ + int accept_flags; /* accept() SOL_SOCKET sockopt flags */ + const struct Namespace *namespaces; /* Pointer to global namespace mapping table */ + struct Namespace *local_namespaces; /* Local namespace mapping table */ + struct soap_nlist *nlist; /* namespace stack */ + struct soap_blist *blist; /* block allocation stack */ + struct soap_clist *clist; /* class instance allocation list */ + void *alist; /* memory allocation (malloc) list */ + struct soap_ilist *iht[SOAP_IDHASH]; + struct soap_plist *pht[SOAP_PTRHASH]; + struct soap_pblk *pblk; /* plist block allocation */ + short pidx; /* plist block allocation */ + struct SOAP_ENV__Header *header; + struct SOAP_ENV__Fault *fault; + int idnum; + void *user; /* to pass user-defined data */ + struct soap_plugin *plugins; /* linked list of plug-in data */ + char *userid; /* HTTP Basic authorization userid */ + char *passwd; /* HTTP Basic authorization passwd */ + int (*fpost)(struct soap*, const char*, const char*, int, const char*, const char*, size_t); + int (*fget)(struct soap*); + int (*fput)(struct soap*); + int (*fdel)(struct soap*); + int (*fhead)(struct soap*); + int (*fform)(struct soap*); + int (*fposthdr)(struct soap*, const char*, const char*); + int (*fresponse)(struct soap*, int, size_t); + int (*fparse)(struct soap*); + int (*fparsehdr)(struct soap*, const char*, const char*); + int (*fheader)(struct soap*); + int (*fresolve)(struct soap*, const char*, struct in_addr* inaddr); + int (*fconnect)(struct soap*, const char*, const char*, int); + int (*fdisconnect)(struct soap*); + int (*fclosesocket)(struct soap*, SOAP_SOCKET); + int (*fshutdownsocket)(struct soap*, SOAP_SOCKET, int); + SOAP_SOCKET (*fopen)(struct soap*, const char*, const char*, int); + SOAP_SOCKET (*faccept)(struct soap*, SOAP_SOCKET, struct sockaddr*, int *n); + int (*fclose)(struct soap*); + int (*fsend)(struct soap*, const char*, size_t); + size_t (*frecv)(struct soap*, char*, size_t); + int (*fpoll)(struct soap*); + void (*fseterror)(struct soap*, const char **c, const char **s); + int (*fignore)(struct soap*, const char*); + int (*fserveloop)(struct soap*); + void *(*fplugin)(struct soap*, const char*); + void *(*fmalloc)(struct soap*, size_t); +#ifndef WITH_LEANER + int (*fprepareinit)(struct soap*); + int (*fpreparesend)(struct soap*, const char*, size_t); + int (*fpreparerecv)(struct soap*, const char*, size_t); + int (*fpreparefinal)(struct soap*); + void *(*fdimereadopen)(struct soap*, void*, const char*, const char*, const char*); + void *(*fdimewriteopen)(struct soap*, const char*, const char*, const char*); + void (*fdimereadclose)(struct soap*, void*); + void (*fdimewriteclose)(struct soap*, void*); + size_t (*fdimeread)(struct soap*, void*, char*, size_t); + int (*fdimewrite)(struct soap*, void*, const char*, size_t); + void *(*fmimereadopen)(struct soap*, void*, const char*, const char*, const char*); + void *(*fmimewriteopen)(struct soap*, void*, const char*, const char*, const char*, enum soap_mime_encoding); + void (*fmimereadclose)(struct soap*, void*); + void (*fmimewriteclose)(struct soap*, void*); + size_t (*fmimeread)(struct soap*, void*, char*, size_t); + int (*fmimewrite)(struct soap*, void*, const char*, size_t); +#endif + SOAP_SOCKET master; + SOAP_SOCKET socket; +#if defined(__cplusplus) && !defined(WITH_LEAN) + std::ostream *os; + std::istream *is; +#else + void *os; /* preserve alignment */ + void *is; /* preserve alignment */ +#endif +#ifndef UNDER_CE + int sendfd; + int recvfd; +#else + FILE *sendfd; + FILE *recvfd; +#endif + size_t bufidx; /* index in soap.buf[] */ + size_t buflen; /* length of soap.buf[] content */ + soap_wchar ahead; /* parser lookahead */ + short cdata; /* CDATA parser state */ + short body; /* parsed XML element has a body or not */ + unsigned int level; /* XML nesting level */ + size_t count; /* message length counter */ + size_t length; /* message length as set by HTTP header */ + char *labbuf; /* look-aside buffer */ + size_t lablen; /* look-aside buffer allocated length */ + size_t labidx; /* look-aside buffer index to available part */ + char buf[SOAP_BUFLEN];/* send and receive buffer */ + char msgbuf[1024]; /* in/output buffer for messages >=1024 bytes */ + char tmpbuf[1024]; /* in/output buffer for HTTP/MIME headers, simpleType values, attribute names, and DIME must be >=1024 bytes */ + char tag[SOAP_TAGLEN]; + char id[SOAP_TAGLEN]; + char href[SOAP_TAGLEN]; + char type[SOAP_TAGLEN]; + char arrayType[SOAP_TAGLEN]; + char arraySize[SOAP_TAGLEN]; + char arrayOffset[SOAP_TAGLEN]; + short other; + short position; + int positions[SOAP_MAXDIMS]; + short root; + struct soap_attribute *attributes; /* attribute list */ + short encoding; /* when set, output encodingStyle */ + short mustUnderstand; /* a mustUnderstand element was parsed or is output */ + short null; /* parsed XML is xsi:nil */ + short ns; /* when not set, output full xmlns bindings */ + short part; /* parsing state */ + short alloced; + short peeked; + size_t chunksize; + size_t chunkbuflen; + char endpoint[SOAP_TAGLEN]; + char path[SOAP_TAGLEN]; + char host[SOAP_TAGLEN]; + char *action; + char *authrealm; /* HTTP authentication realm */ + char *prolog; /* XML declaration prolog */ + unsigned long ip; /* IP number */ + int port; /* port number */ + short keep_alive; /* connection should be kept open */ + short tcp_keep_alive; /* enable SO_KEEPALIVE */ + unsigned int tcp_keep_idle; /* set TCP_KEEPIDLE */ + unsigned int tcp_keep_intvl; /* set TCP_KEEPINTVL */ + unsigned int tcp_keep_cnt; /* set TCP_KEEPCNT */ + unsigned int max_keep_alive; /* maximum keep-alive session (default=100) */ + const char *proxy_http_version;/* HTTP version of proxy "1.0" or "1.1" */ + const char *proxy_host; /* Proxy Server host name */ + int proxy_port; /* Proxy Server port (default = 8080) */ + const char *proxy_userid; /* Proxy Authorization user name */ + const char *proxy_passwd; /* Proxy Authorization password */ + const char *proxy_from; /* X-Forwarding-For header returned by proxy */ + int status; /* -1 when request, else error code to be returned by server */ + int error; + int errmode; + int errnum; +#ifndef WITH_LEANER + struct soap_dom_element *dom; + struct soap_dime dime; + struct soap_mime mime; + struct soap_xlist *xlist; +#endif +#if !defined(WITH_LEAN) || defined(SOAP_DEBUG) + const char *logfile[SOAP_MAXLOGS]; + FILE *fdebug[SOAP_MAXLOGS]; + struct soap_mlist *mht[SOAP_PTRHASH]; +#endif +#ifndef WITH_LEAN + const char *c14ninclude; + const char *c14nexclude; + struct soap_cookie *cookies; + const char *cookie_domain; + const char *cookie_path; + int cookie_max; +#endif +#ifndef WITH_NOIO +#ifdef WITH_IPV6 + struct sockaddr_storage peer; /* IPv6: set by soap_accept and by UDP recv */ +#else + struct sockaddr_in peer; /* IPv4: set by soap_connect/soap_accept and by UDP recv */ +#endif +#endif + size_t peerlen; +#ifdef WITH_OPENSSL + int (*fsslauth)(struct soap*); + int (*fsslverify)(int, X509_STORE_CTX*); + BIO *bio; + SSL *ssl; + SSL_CTX *ctx; + SSL_SESSION *session; +#else + void *fsslauth; /* dummy members, to preserve alignment */ + void *fsslverify; + void *bio; + void *ssl; + void *ctx; + void *session; +#endif + unsigned short ssl_flags; + const char *keyfile; + const char *password; + const char *dhfile; + const char *cafile; + const char *capath; + const char *crlfile; + const char *randfile; + char session_host[SOAP_TAGLEN]; + int session_port; +#ifdef WITH_ZLIB + z_stream *d_stream; /* decompression stream */ + uLong z_crc; /* internal gzip crc */ +#else + void *d_stream; /* dummy members, to preserve alignment */ + soap_int32 z_crc; +#endif + short zlib_state; /* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_INFLATE */ + short zlib_in; /* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_GZIP */ + short zlib_out; /* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_GZIP */ + char *z_buf; /* buffer */ + size_t z_buflen; + unsigned short z_level; /* compression level to be used (0=none, 1=fast to 9=best) */ + float z_ratio_in; /* detected compression ratio compressed_length/length of inbound message */ + float z_ratio_out; /* detected compression ratio compressed_length/length of outbound message */ +#ifdef WMW_RPM_IO + void *rpmreqid; +#endif +#ifdef __cplusplus + soap(); + soap(soap_mode); + soap(soap_mode, soap_mode); + soap(struct soap&); + virtual ~soap(); +#endif +}; + +struct soap_code_map +{ long code; + const char *string; +}; + +/* forwarding list */ +struct soap_flist +{ struct soap_flist *next; + int type; + void *ptr; + unsigned int level; + size_t len; + void (*fcopy)(struct soap*, int, int, void*, size_t, const void*, size_t); +}; + +/* id-ref forwarding list */ +struct soap_ilist +{ struct soap_ilist *next; + int type; + size_t size; + void *link; + void *copy; + struct soap_flist *flist; + void *ptr; + unsigned int level; + char id[1]; /* the actual id string value flows into the allocated region below this struct */ +}; + +struct soap_plugin +{ struct soap_plugin *next; + const char *id; + void *data; + int (*fcopy)(struct soap *soap, struct soap_plugin *dst, struct soap_plugin *src); + void (*fdelete)(struct soap *soap, struct soap_plugin *p); /* should delete fields of plugin only and not free(p) */ +}; + +#ifndef WITH_NONAMESPACES +extern SOAP_NMAC struct Namespace namespaces[]; +#endif + +#ifndef WITH_LEAN +# define soap_get0(soap) (((soap)->bufidx>=(soap)->buflen && soap_recv(soap)) ? EOF : (unsigned char)(soap)->buf[(soap)->bufidx]) +# define soap_get1(soap) (((soap)->bufidx>=(soap)->buflen && soap_recv(soap)) ? EOF : (unsigned char)(soap)->buf[(soap)->bufidx++]) +#else +soap_wchar soap_get0(struct soap*); +soap_wchar soap_get1(struct soap*); +#endif + +#define soap_revget1(soap) ((soap)->bufidx--) +#define soap_unget(soap, c) ((soap)->ahead = c) +#define soap_register_plugin(soap, plugin) soap_register_plugin_arg(soap, plugin, NULL) +#define soap_imode(soap, n) ((soap)->mode = (soap)->imode = (n)) +#define soap_set_imode(soap, n) ((soap)->imode |= (n)) +#define soap_clr_imode(soap, n) ((soap)->imode &= ~(n)) +#define soap_omode(soap, n) ((soap)->mode = (soap)->omode = (n)) +#define soap_set_omode(soap, n) ((soap)->omode |= (n)) +#define soap_clr_omode(soap, n) ((soap)->omode &= ~(n)) +#define soap_set_mode(soap, n) ((soap)->imode |= (n), (soap)->omode |= (n)) +#define soap_clr_mode(soap, n) ((soap)->imode &= ~(n), (soap)->omode &= ~(n)) +#define soap_destroy(soap) soap_delete((soap), NULL) + +#ifdef HAVE_STRRCHR +# define soap_strrchr(s, t) strrchr(s, t) +#else + SOAP_FMAC1 char* SOAP_FMAC2 soap_strrchr(const char *s, int t); +#endif + +#ifdef HAVE_STRTOL +# define soap_strtol(s, t, b) strtol(s, t, b) +#else + SOAP_FMAC1 long SOAP_FMAC2 soap_strtol(const char *s, char **t, int b); +#endif + +#ifdef HAVE_STRTOUL +# define soap_strtoul(s, t, b) strtoul(s, t, b) +#else + SOAP_FMAC1 unsigned long SOAP_FMAC2 soap_strtoul(const char *s, char **t, int b); +#endif + +#if defined(WITH_OPENSSL) +# define soap_random soap_rand() +SOAP_FMAC1 int SOAP_FMAC2 soap_rand(void); +#elif defined(HAVE_RANDOM) +# define soap_random (int)random() +#else +# define soap_random rand() +#endif + +#ifdef WITH_NOIDREF +# define soap_embedded(s, p, t) (0) +# define soap_id_lookup(s, i, p, t, n, k) (p) +# define soap_id_forward(s, h, p, len, st, tt, n, k, fc) (p) +# define soap_reference(s, a, t) (1) +# define soap_array_reference(s, p, a, n, t) (1) +# define soap_embed(s, p, a, n, t, pp) (0) +# define soap_embedded_id(s, i, p, t) (i) +# define soap_is_embedded(s, p) (0) +# define soap_is_single(s, p) (1) +# define soap_lookup_type(s, i) (0) +# define soap_getindependent(s) (0) +# define soap_putindependent(s) (0) +# define soap_getelement(s, n) (n) +# define soap_putelement(s, p, t, i, n) (0) +# define soap_markelement(s, p, n) (0) +#endif + +SOAP_FMAC1 void SOAP_FMAC2 soap_header(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_fault(struct soap*); +SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultcode(struct soap*); +SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultsubcode(struct soap*); +SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultstring(struct soap*); +SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultdetail(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_serializeheader(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putheader(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getheader(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_serializefault(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putfault(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getfault(struct soap*); + +SOAP_FMAC1 void SOAP_FMAC2 soap_ssl_init(); +SOAP_FMAC1 int SOAP_FMAC2 soap_poll(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_connect_command(struct soap*, int, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_connect(struct soap*, const char*, const char*); +SOAP_FMAC1 SOAP_SOCKET SOAP_FMAC2 soap_bind(struct soap*, const char*, int, int); +SOAP_FMAC1 SOAP_SOCKET SOAP_FMAC2 soap_accept(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_accept(struct soap*); +SOAP_FMAC1 const char * SOAP_FMAC2 soap_ssl_error(struct soap*, int); + +SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_server_context(struct soap*, unsigned short, const char*, const char*, const char*, const char*, const char*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_client_context(struct soap*, unsigned short, const char*, const char*, const char*, const char*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_puthttphdr(struct soap*, int status, size_t count); + +SOAP_FMAC1 const char* SOAP_FMAC2 soap_get_header_attribute(struct soap*, const char*, const char*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_decode_key(char*, size_t, const char*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_decode_val(char*, size_t, const char*); + +SOAP_FMAC1 size_t SOAP_FMAC2 soap_hash(const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_endpoint(struct soap*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_flush_raw(struct soap*, const char*, size_t); +SOAP_FMAC1 int SOAP_FMAC2 soap_flush(struct soap*); +SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_get(struct soap*); +SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_getchar(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_tag_cmp(const char*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_fault(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_sender_fault(struct soap*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_sender_fault_subcode(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_receiver_fault(struct soap*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_receiver_fault_subcode(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_sender_error(struct soap*, const char*, const char*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_receiver_error(struct soap*, const char*, const char*, int); + +SOAP_FMAC1 int SOAP_FMAC2 soap_send_raw(struct soap*, const char*, size_t); +SOAP_FMAC1 int SOAP_FMAC2 soap_recv_raw(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_recv(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_send(struct soap*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_send2(struct soap*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_send3(struct soap*, const char*, const char*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_pututf8(struct soap*, unsigned long); +SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_getutf8(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_putbase64(struct soap*, const unsigned char*, int); +SOAP_FMAC1 unsigned char* SOAP_FMAC2 soap_getbase64(struct soap*, int*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_puthex(struct soap*, const unsigned char*, int); +SOAP_FMAC1 unsigned char* SOAP_FMAC2 soap_gethex(struct soap*, int*); + +#ifndef WITH_LEANER +SOAP_FMAC1 int SOAP_FMAC2 soap_xop_forward(struct soap*, unsigned char**, int*, char**, char**, char**); +SOAP_FMAC1 int SOAP_FMAC2 soap_dime_forward(struct soap*, unsigned char**, int*, char**, char**, char**); +#endif + +#ifndef WITH_NOIDREF +SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_lookup_id(struct soap*, void *p, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_lookup(struct soap*, const void *p, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_enter(struct soap*, const void *p, const struct soap_array *a, int n, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_array_pointer_lookup(struct soap*, const void *p, const struct soap_array *a, int n, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_embed(struct soap *soap, const void *p, const struct soap_array *a, int n, const char *tag, int type); +SOAP_FMAC1 struct soap_ilist* SOAP_FMAC2 soap_lookup(struct soap*, const char*); +SOAP_FMAC1 struct soap_ilist* SOAP_FMAC2 soap_enter(struct soap*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_resolve(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_embedded(struct soap*, const void *p, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_reference(struct soap*, const void *p, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_array_reference(struct soap*, const void *p, const struct soap_array *a, int n, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_embedded_id(struct soap*, int id, const void *p, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_is_embedded(struct soap*, struct soap_plist*); +SOAP_FMAC1 int SOAP_FMAC2 soap_is_single(struct soap*, struct soap_plist*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_embedded(struct soap*, struct soap_plist*); +#endif + +SOAP_FMAC1 int SOAP_FMAC2 soap_begin_count(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_end_count(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_begin_send(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_end_send(struct soap*); + +SOAP_FMAC1 const struct soap_code_map* SOAP_FMAC2 soap_code(const struct soap_code_map*, const char*); +SOAP_FMAC1 long SOAP_FMAC2 soap_code_int(const struct soap_code_map*, const char*, long); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_code_str(const struct soap_code_map*, long); +SOAP_FMAC1 long SOAP_FMAC2 soap_code_bits(const struct soap_code_map*, const char*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_code_list(struct soap*, const struct soap_code_map*, long); + +SOAP_FMAC1 int SOAP_FMAC2 soap_getline(struct soap*, char*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_begin_recv(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_end_recv(struct soap*); + +SOAP_FMAC1 void* SOAP_FMAC2 soap_malloc(struct soap*, size_t); +SOAP_FMAC1 void SOAP_FMAC2 soap_dealloc(struct soap*, void*); +SOAP_FMAC1 struct soap_clist * SOAP_FMAC2 soap_link(struct soap*, void*, int, int, int (*fdelete)(struct soap_clist*)); +SOAP_FMAC1 void SOAP_FMAC2 soap_unlink(struct soap*, const void*); +SOAP_FMAC1 void SOAP_FMAC2 soap_free_temp(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_del(struct soap*); + +SOAP_FMAC1 void* SOAP_FMAC2 soap_track_malloc(struct soap*, const char*, int, size_t); +SOAP_FMAC1 void SOAP_FMAC2 soap_track_free(struct soap*, const char*, int, void*); + +#ifndef WITH_NOIDREF +SOAP_FMAC1 int SOAP_FMAC2 soap_lookup_type(struct soap*, const char *id); +SOAP_FMAC1 void* SOAP_FMAC2 soap_id_lookup(struct soap*, const char *id, void **p, int t, size_t n, unsigned int k); +SOAP_FMAC1 void* SOAP_FMAC2 soap_id_forward(struct soap*, const char *id, void *p, size_t len, int st, int tt, size_t n, unsigned int k, void(*fcopy)(struct soap*, int, int, void*, size_t, const void*, size_t)); +#endif +SOAP_FMAC1 void* SOAP_FMAC2 soap_id_enter(struct soap*, const char *id, void *p, int t, size_t n, unsigned int k, const char *type, const char *arrayType, void *(*finstantiate)(struct soap*, int, const char*, const char*, size_t*)); +SOAP_FMAC1 void SOAP_FMAC2 soap_fcopy(struct soap *soap, int st, int tt, void *p, size_t, const void *q, size_t n); + +SOAP_FMAC1 int SOAP_FMAC2 soap_size(const int *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_getoffsets(const char *, const int *, int *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_getsize(const char *, const char *, int *); +SOAP_FMAC1 int SOAP_FMAC2 soap_getsizes(const char *, int *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_getposition(const char *, int *); + +SOAP_FMAC1 char* SOAP_FMAC2 soap_putsize(struct soap*, const char *, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_putsizesoffsets(struct soap*, const char *, const int *, const int *, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_putsizes(struct soap*, const char *, const int *, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_putoffset(struct soap*, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_putoffsets(struct soap*, const int *, int); + +SOAP_FMAC1 int SOAP_FMAC2 soap_closesock(struct soap*); + +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_new(void); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_new1(soap_mode); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_new2(soap_mode, soap_mode); +SOAP_FMAC1 void SOAP_FMAC2 soap_free(struct soap*); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_copy(const struct soap*); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_copy_context(struct soap*, const struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_copy_stream(struct soap*, struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_init(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_init1(struct soap*, soap_mode); +SOAP_FMAC1 void SOAP_FMAC2 soap_init2(struct soap*, soap_mode, soap_mode); +SOAP_FMAC1 void SOAP_FMAC2 soap_done(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_cleanup(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_begin(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_end(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_delete(struct soap*, void*); + +#ifdef SOAP_DEBUG +SOAP_FMAC1 void SOAP_FMAC2 soap_set_recv_logfile(struct soap*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_sent_logfile(struct soap*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_test_logfile(struct soap*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_close_logfiles(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_open_logfile(struct soap*, int); +#endif + +SOAP_FMAC1 const char* SOAP_FMAC2 soap_value(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_match_tag(struct soap*, const char*, const char *); +SOAP_FMAC1 int SOAP_FMAC2 soap_match_array(struct soap*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_element(struct soap*, const char*, int, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_begin_out(struct soap*, const char *tag, int id, const char *type); +SOAP_FMAC1 int SOAP_FMAC2 soap_array_begin_out(struct soap*, const char *tag, int id, const char *type, const char *offset); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_ref(struct soap*, const char *tag, int id, int href); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_href(struct soap*, const char *tag, int id, const char *ref, const char *val); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_null(struct soap*, const char *tag, int id, const char *type); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_id(struct soap*, const char *tag, int id, const void *p, const struct soap_array *a, int d, const char *type, int n); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_result(struct soap*, const char *tag); +SOAP_FMAC1 void SOAP_FMAC2 soap_check_result(struct soap*, const char *tag); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_end_out(struct soap*, const char *tag); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_start_end_out(struct soap*, const char *tag); + +SOAP_FMAC1 int SOAP_FMAC2 soap_attribute(struct soap*, const char*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_element_begin_in(struct soap*, const char *tag, int nillable, const char *type); + +SOAP_FMAC1 int SOAP_FMAC2 soap_element_end_in(struct soap*, const char *tag); + +SOAP_FMAC1 int SOAP_FMAC2 soap_peek_element(struct soap*); + +SOAP_FMAC1 void SOAP_FMAC2 soap_retry(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_revert(struct soap*); + +SOAP_FMAC1 char* SOAP_FMAC2 soap_strdup(struct soap*, const char*); +SOAP_FMAC1 wchar_t* SOAP_FMAC2 soap_wstrdup(struct soap*, const wchar_t*); +SOAP_FMAC1 const char * SOAP_FMAC2 soap_strsearch(const char *big, const char *little); + +SOAP_FMAC1 int SOAP_FMAC2 soap_string_out(struct soap*, const char *s, int flag); +SOAP_FMAC1 char* SOAP_FMAC2 soap_string_in(struct soap*, int, long, long); + +#ifndef WITH_LEANER +SOAP_FMAC1 int SOAP_FMAC2 soap_wstring_out(struct soap*, const wchar_t *s, int flag); +SOAP_FMAC1 wchar_t* SOAP_FMAC2 soap_wstring_in(struct soap*, int, long, long); +#endif + +SOAP_FMAC1 int SOAP_FMAC2 soap_match_namespace(struct soap*, const char *, const char*, size_t n1, size_t n2); + +SOAP_FMAC1 int SOAP_FMAC2 soap_set_namespaces(struct soap*, const struct Namespace*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_local_namespaces(struct soap*); + +SOAP_FMAC1 void SOAP_FMAC2 soap_pop_namespace(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_push_namespace(struct soap*, const char *,const char *); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_current_namespace(struct soap *soap, const char *tag); + +SOAP_FMAC1 struct soap_nlist* SOAP_FMAC2 soap_lookup_ns(struct soap *soap, const char *tag, size_t n); + +SOAP_FMAC1 int SOAP_FMAC2 soap_store_lab(struct soap*, const char*, size_t); +SOAP_FMAC1 int SOAP_FMAC2 soap_append_lab(struct soap*, const char*, size_t); + +SOAP_FMAC1 int SOAP_FMAC2 soap_new_block(struct soap*); +SOAP_FMAC1 void* SOAP_FMAC2 soap_push_block(struct soap*, size_t); +SOAP_FMAC1 void SOAP_FMAC2 soap_pop_block(struct soap*); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_size_block(struct soap*, size_t); +SOAP_FMAC1 char* SOAP_FMAC2 soap_first_block(struct soap*); +SOAP_FMAC1 char* SOAP_FMAC2 soap_next_block(struct soap*); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_block_size(struct soap*); +SOAP_FMAC1 char* SOAP_FMAC2 soap_save_block(struct soap*, char*, int); +SOAP_FMAC1 void SOAP_FMAC2 soap_end_block(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_begin_out(struct soap*); +SOAP_FMAC1 int soap_envelope_end_out(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_begin_in(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_end_in(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_body_begin_out(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_body_end_out(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_body_begin_in(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_body_end_in(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_recv_header(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_response(struct soap*, int); + +SOAP_FMAC1 int SOAP_FMAC2 soap_send_empty_response(struct soap*, int status); +SOAP_FMAC1 int SOAP_FMAC2 soap_recv_empty_response(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_send_fault(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_recv_fault(struct soap*); + +#ifndef WITH_NOSTDLIB +SOAP_FMAC1 void SOAP_FMAC2 soap_print_fault(struct soap*, FILE*); +SOAP_FMAC1 void SOAP_FMAC2 soap_print_fault_location(struct soap*, FILE*); +# ifndef WITH_LEAN +# ifdef __cplusplus +SOAP_FMAC1 void SOAP_FMAC2 soap_stream_fault(struct soap*, std::ostream&); +# endif +SOAP_FMAC1 char* SOAP_FMAC2 soap_sprint_fault(struct soap*, char*, size_t); +# endif +#endif + +SOAP_FMAC1 int SOAP_FMAC2 soap_s2byte(struct soap*, const char*, char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2short(struct soap*, const char*, short*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2int(struct soap*, const char*, int*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2long(struct soap*, const char*, long*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2LONG64(struct soap*, const char*, LONG64*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2float(struct soap*, const char*, float*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2double(struct soap*, const char*, double*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedByte(struct soap*, const char*, unsigned char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedShort(struct soap*, const char*, unsigned short*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedInt(struct soap*, const char*, unsigned int*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedLong(struct soap*, const char*, unsigned long*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2ULONG64(struct soap*, const char*, ULONG64*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2string(struct soap*, const char*, char**); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2QName(struct soap*, const char*, char**); + +#ifndef WITH_LEAN +SOAP_FMAC1 int SOAP_FMAC2 soap_s2wchar(struct soap*, const char*, wchar_t**); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2dateTime(struct soap*, const char*, time_t*); +SOAP_FMAC1 char* SOAP_FMAC2 soap_s2base64(struct soap*, const unsigned char*, char*, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_s2hex(struct soap*, const unsigned char*, char*, int); +#endif + +SOAP_FMAC1 const char* SOAP_FMAC2 soap_byte2s(struct soap*, char); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_short2s(struct soap*, short); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_int2s(struct soap*, int); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_long2s(struct soap*, long); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_LONG642s(struct soap*, LONG64); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_float2s(struct soap*, float); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_double2s(struct soap*, double); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedByte2s(struct soap*, unsigned char); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedShort2s(struct soap*, unsigned short); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedInt2s(struct soap*, unsigned int); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedLong2s(struct soap*, unsigned long); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_ULONG642s(struct soap*, ULONG64); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_QName2s(struct soap*, const char*); + +#ifndef WITH_LEAN +SOAP_FMAC1 const char* SOAP_FMAC2 soap_wchar2s(struct soap*, const wchar_t*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_dateTime2s(struct soap*, time_t); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_base642s(struct soap*, const char*, char*, size_t, int*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_hex2s(struct soap*, const char*, char*, size_t, int*); +#endif + + +SOAP_FMAC1 int* SOAP_FMAC2 soap_inint(struct soap*, const char *tag, int *p, const char *, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_inbyte(struct soap*, const char *tag, char *p, const char *, int); +SOAP_FMAC1 long* SOAP_FMAC2 soap_inlong(struct soap*, const char *tag, long *p, const char *, int); +SOAP_FMAC1 LONG64* SOAP_FMAC2 soap_inLONG64(struct soap*, const char *tag, LONG64 *p, const char *, int); +SOAP_FMAC1 short* SOAP_FMAC2 soap_inshort(struct soap*, const char *tag, short *p, const char *, int); +SOAP_FMAC1 float* SOAP_FMAC2 soap_infloat(struct soap*, const char *tag, float *p, const char *, int); +SOAP_FMAC1 double* SOAP_FMAC2 soap_indouble(struct soap*, const char *tag, double *p, const char *, int); +SOAP_FMAC1 unsigned char* SOAP_FMAC2 soap_inunsignedByte(struct soap*, const char *tag, unsigned char *p, const char *, int); +SOAP_FMAC1 unsigned short* SOAP_FMAC2 soap_inunsignedShort(struct soap*, const char *tag, unsigned short *p, const char *, int); +SOAP_FMAC1 unsigned int* SOAP_FMAC2 soap_inunsignedInt(struct soap*, const char *tag, unsigned int *p, const char *, int); +SOAP_FMAC1 unsigned long* SOAP_FMAC2 soap_inunsignedLong(struct soap*, const char *tag, unsigned long *p, const char *, int); +SOAP_FMAC1 ULONG64* SOAP_FMAC2 soap_inULONG64(struct soap*, const char *tag, ULONG64 *p, const char *, int); +SOAP_FMAC1 char** SOAP_FMAC2 soap_instring(struct soap*, const char *tag, char **p, const char *, int, int, long, long); +SOAP_FMAC1 char** SOAP_FMAC2 soap_inliteral(struct soap*, const char *tag, char **p); + +#ifndef WITH_LEAN +SOAP_FMAC1 time_t* SOAP_FMAC2 soap_indateTime(struct soap*, const char *tag, time_t *p, const char *, int); +SOAP_FMAC1 time_t SOAP_FMAC2 soap_timegm(struct tm*); +#endif + +#ifndef WITH_LEANER +SOAP_FMAC1 wchar_t** SOAP_FMAC2 soap_inwstring(struct soap*, const char *tag, wchar_t **p, const char *, int, long, long); +SOAP_FMAC1 wchar_t** SOAP_FMAC2 soap_inwliteral(struct soap*, const char *tag, wchar_t **p); +#endif + +SOAP_FMAC1 int SOAP_FMAC2 soap_outbyte(struct soap*, const char *tag, int id, const char *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outshort(struct soap*, const char *tag, int id, const short *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outint(struct soap*, const char *tag, int id, const int *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outlong(struct soap*, const char *tag, int id, const long *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outLONG64(struct soap*, const char *tag, int id, const LONG64 *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outfloat(struct soap*, const char *tag, int id, const float *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outdouble(struct soap*, const char *tag, int id, const double *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedByte(struct soap*, const char *tag, int id, const unsigned char *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedShort(struct soap*, const char *tag, int id, const unsigned short *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedInt(struct soap*, const char *tag, int id, const unsigned int *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedLong(struct soap*, const char *tag, int id, const unsigned long *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outULONG64(struct soap*, const char *tag, int id, const ULONG64 *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outstring(struct soap*, const char *tag, int id, char *const*p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outliteral(struct soap*, const char *tag, char *const*p, const char *type); + +#ifndef WITH_LEAN +SOAP_FMAC1 int SOAP_FMAC2 soap_outdateTime(struct soap*, const char *tag, int id, const time_t *p, const char *, int); +#endif + +#ifndef WITH_LEANER +SOAP_FMAC1 int SOAP_FMAC2 soap_outwstring(struct soap*, const char *tag, int id, wchar_t *const*p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outwliteral(struct soap*, const char *tag, wchar_t *const*p, const char *type); +#endif + +#ifndef WITH_LEANER +SOAP_FMAC1 int SOAP_FMAC2 soap_attachment(struct soap *, const char*, int, const void*, const struct soap_array*, const char*, const char*, const char*, int, const char*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_move(struct soap*, long); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_tell(struct soap*); +SOAP_FMAC1 char* SOAP_FMAC2 soap_dime_option(struct soap*, unsigned short, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getdimehdr(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getdime(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putdimehdr(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putdime(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getmimehdr(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getmime(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putmimehdr(struct soap*, struct soap_multipart*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putmime(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_dime(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_mime(struct soap*, const char *boundary, const char *start); +SOAP_FMAC1 void SOAP_FMAC2 soap_clr_dime(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_clr_mime(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_dime_attachment(struct soap*, char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_mime_attachment(struct soap*, char *ptr, size_t size, enum soap_mime_encoding encoding, const char *type, const char *id, const char *location, const char *description); +SOAP_FMAC1 void SOAP_FMAC2 soap_post_check_mime_attachments(struct soap *soap); +SOAP_FMAC1 int SOAP_FMAC2 soap_check_mime_attachments(struct soap *soap); +SOAP_FMAC1 struct soap_multipart* SOAP_FMAC2 soap_get_mime_attachment(struct soap *soap, void *handle); +SOAP_FMAC1 struct soap_multipart* SOAP_FMAC2 soap_next_multipart(struct soap_multipart*); +SOAP_FMAC1 int SOAP_FMAC2 soap_match_cid(struct soap*, const char*, const char*); +#endif + +SOAP_FMAC1 int SOAP_FMAC2 soap_register_plugin_arg(struct soap*, int (*fcreate)(struct soap*, struct soap_plugin*, void*), void*); +SOAP_FMAC1 void* SOAP_FMAC2 soap_lookup_plugin(struct soap*, const char*); + +SOAP_FMAC1 const char* SOAP_FMAC2 soap_attr_value(struct soap *soap, const char *name, int flag); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_attr(struct soap *soap, const char *name, const char *value); +SOAP_FMAC1 void SOAP_FMAC2 soap_clr_attr(struct soap *soap); + +#ifdef WITH_COOKIES +SOAP_FMAC1 void SOAP_FMAC2 soap_getcookies(struct soap *soap, const char *val); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_encode_cookie(const char*, char*, size_t); +SOAP_FMAC1 extern struct soap_cookie* SOAP_FMAC2 soap_set_cookie(struct soap*, const char*, const char*, const char*, const char*); +SOAP_FMAC1 extern struct soap_cookie* SOAP_FMAC2 soap_cookie(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern char* SOAP_FMAC2 soap_cookie_value(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern char* SOAP_FMAC2 soap_env_cookie_value(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern time_t SOAP_FMAC2 soap_cookie_expire(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern int SOAP_FMAC2 soap_set_cookie_expire(struct soap*, const char*, long, const char*, const char*); +SOAP_FMAC1 extern int SOAP_FMAC2 soap_set_cookie_session(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern int SOAP_FMAC2 soap_clr_cookie_session(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern void SOAP_FMAC2 soap_clr_cookie(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern int SOAP_FMAC2 soap_getenv_cookies(struct soap*); +SOAP_FMAC1 extern struct soap_cookie* SOAP_FMAC2 soap_copy_cookies(struct soap*, const struct soap*); +SOAP_FMAC1 extern void SOAP_FMAC2 soap_free_cookies(struct soap*); +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.6b.c b/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.6b.c new file mode 100644 index 0000000..6b7160b --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.6b.c @@ -0,0 +1,13101 @@ +/* + +stdsoap2.c[pp] 2.7.6b + +gSOAP runtime + +gSOAP XML Web services tools +Copyright (C) 2000-2005, Robert van Engelen, Genivia Inc., All Rights Reserved. +This part of the software is released under one of the following licenses: +GPL, the gSOAP public license, or Genivia's license for commercial use. +-------------------------------------------------------------------------------- +Contributors: + +Wind River Systems, Inc., for the following additions: + - vxWorks compatible +-------------------------------------------------------------------------------- +gSOAP public license. + +The contents of this file are subject to the gSOAP Public License Version 1.3 +(the "License"); you may not use this file except in compliance with the +License. You may obtain a copy of the License at +http://www.cs.fsu.edu/~engelen/soaplicense.html +Software distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +for the specific language governing rights and limitations under the License. + +The Initial Developer of the Original Code is Robert A. van Engelen. +Copyright (C) 2000-2005, Robert van Engelen, Genivia Inc., All Rights Reserved. +-------------------------------------------------------------------------------- +GPL license. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA + +Author contact information: +engelen@genivia.com / engelen@acm.org +-------------------------------------------------------------------------------- +A commercial use license is available from Genivia, Inc., contact@genivia.com +-------------------------------------------------------------------------------- + +Installation note: + +Win32 build needs winsock.dll (Visual C++ "wsock32.lib") +To do this in Visual C++ 6.0, go to "Project", "settings", select the "Link" +tab (the project file needs to be selected in the file view) and add +"wsock32.lib" to the "Object/library modules" entry + +On Mac OS X with gcc (GCC) 3.1 20020420 (prerelease) you MUST compile with +-fstack_check when using -O2 because gcc 3.1 has a bug that smashes the stack +when locally allocated data exceeds 64K. + +*/ + +#include "stdsoap2.h" + +#ifdef __cplusplus +SOAP_SOURCE_STAMP("@(#) stdsoap2.cpp ver 2.7.6b 2005-08-26 12:00:00 GMT") +extern "C" { +#else +SOAP_SOURCE_STAMP("@(#) stdsoap2.c ver 2.7.6b 2005-08-26 12:00:00 GMT") +#endif + +/* 8bit character representing unknown/nonrepresentable character data (e.g. not supported by current locale with multibyte support enabled) */ +#ifndef SOAP_UNKNOWN_CHAR +#define SOAP_UNKNOWN_CHAR (127) +#endif + +/* EOF=-1 */ +#define SOAP_LT (soap_wchar)(-2) /* XML character '<' */ +#define SOAP_TT (soap_wchar)(-3) /* XML character '' */ +#define SOAP_QT (soap_wchar)(-5) /* XML character '"' */ +#define SOAP_AP (soap_wchar)(-6) /* XML character ''' */ + +#define SOAP_BOM (soap_wchar)(0xFEFF) /* UTF BOM is Unicode FEFF */ + +#define soap_blank(c) ((c) >= 0 && (c) <= 32) +#define soap_notblank(c) ((c) > 32) +#define soap_hash_ptr(p) (((unsigned long)(p) >> 3) & (SOAP_PTRHASH - 1)) + +static int soap_isxdigit(int); +static soap_wchar soap_char(struct soap*); + +#ifndef WITH_NOIDREF +static void soap_update_ptrs(struct soap*, char*, char*, long); +static int soap_has_copies(struct soap*, const char*, const char*); +static void soap_init_iht(struct soap*); +static void soap_free_iht(struct soap*); +static void soap_init_pht(struct soap*); +static void soap_free_pht(struct soap*); +#endif + +#ifdef SOAP_DEBUG +static void soap_init_logs(struct soap*); +static void soap_close_logfile(struct soap*, int); +static void soap_set_logfile(struct soap*, int, const char*); +static void soap_free_mht(struct soap*); +static void soap_track_unlink(struct soap*, const void*); +#endif + +static int soap_set_error(struct soap*, const char*, const char*, const char*, const char*, int); +static int soap_copy_fault(struct soap*, const char*, const char*, const char*, const char*); +static int soap_getattrval(struct soap*, char*, size_t, soap_wchar); +static void *fplugin(struct soap*, const char*); + +#ifndef WITH_LEAN +static const char *soap_set_validation_fault(struct soap*, const char*, const char*); +static int soap_isnumeric(struct soap*, const char*); +static time_t soap_timegm(struct tm*); +static struct soap_nlist *soap_lookup_ns(struct soap *soap, const char *tag, size_t n); +static struct soap_nlist *soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized); +static void soap_pop_ns(struct soap *soap); +static void soap_utilize_ns(struct soap *soap, const char *tag, size_t n); +#endif + +#ifndef WITH_LEANER +static struct soap_multipart *soap_new_multipart(struct soap*, struct soap_multipart**, struct soap_multipart**, char*, size_t); +static int soap_putdimefield(struct soap*, const char*, size_t); +static char *soap_getdimefield(struct soap*, size_t); +static void soap_select_mime_boundary(struct soap*); +static int soap_valid_mime_boundary(struct soap*); +static int soap_match_cid(const char*, const char*); +static void soap_resolve_attachment(struct soap*, struct soap_multipart*); +#endif + +#ifdef WITH_GZIP +static int soap_getgziphdr(struct soap*); +#endif + +#ifdef WITH_OPENSSL +static void ssl_init(); +static int ssl_auth_init(struct soap*); +static int ssl_verify_callback(int, X509_STORE_CTX*); +static int ssl_password(char*, int, int, void *); +static const char *ssl_error(struct soap*, int); +/* This callback is included for future references. It should not be deleted +static DH *ssl_tmp_dh(SSL*, int, int); +*/ +#endif + +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +static const char *soap_decode(char*, size_t, const char*, const char*); +#endif + +#ifndef WITH_NOHTTP +static soap_wchar soap_getchunkchar(struct soap*); +static const char *http_error(struct soap*, int); +static int http_post(struct soap*, const char*, const char*, int, const char*, const char*, size_t); +static int http_get(struct soap*); +static int http_send_header(struct soap*, const char*); +static int http_post_header(struct soap*, const char*, const char*); +static int http_response(struct soap*, int, size_t); +static int http_parse(struct soap*); +static int http_parse_header(struct soap*, const char*, const char*); +#endif + +#ifndef WITH_NOIO +static int fsend(struct soap*, const char*, size_t); +static size_t frecv(struct soap*, char*, size_t); +static int tcp_init(struct soap*); +static const char *tcp_error(struct soap*); +#ifndef WITH_IPV6 +static int tcp_gethost(struct soap*, const char *addr, struct in_addr *inaddr); +#endif +static int tcp_connect(struct soap*, const char *endpoint, const char *host, int port); +static int tcp_accept(struct soap*, int, struct sockaddr*, int*); +static int tcp_disconnect(struct soap*); +static int tcp_closesocket(struct soap*, SOAP_SOCKET); +static int tcp_shutdownsocket(struct soap*, SOAP_SOCKET, int); +static const char *soap_strerror(struct soap*); +#endif + +#ifdef VXWORKS +static int vx_nonblocking = TRUE; /* ioctl argument */ +#endif + +#if defined(PALM) && !defined(PALM_2) +unsigned short errno; +#endif + +#ifndef PALM_1 +static const char soap_env1[42] = "http://schemas.xmlsoap.org/soap/envelope/"; +static const char soap_enc1[42] = "http://schemas.xmlsoap.org/soap/encoding/"; +static const char soap_env2[40] = "http://www.w3.org/2003/05/soap-envelope"; +static const char soap_enc2[40] = "http://www.w3.org/2003/05/soap-encoding"; +static const char soap_rpc[35] = "http://www.w3.org/2003/05/soap-rpc"; +#endif + +#ifndef PALM_1 +const struct soap_double_nan soap_double_nan = {0xFFFFFFFF, 0xFFFFFFFF}; +static const char soap_base64o[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char soap_base64i[81] = "\76XXX\77\64\65\66\67\70\71\72\73\74\75XXXXXXX\00\01\02\03\04\05\06\07\10\11\12\13\14\15\16\17\20\21\22\23\24\25\26\27\30\31XXXXXX\32\33\34\35\36\37\40\41\42\43\44\45\46\47\50\51\52\53\54\55\56\57\60\61\62\63"; +#endif + +#ifndef WITH_LEAN +static const char soap_indent[11] = "\n\t\t\t\t\t\t\t\t\t"; +/* Alternative indentation form for SOAP_XML_INDENT: +static const char soap_indent[21] = "\n "; +*/ +#endif + +static const char soap_padding[3] = "\0\0"; +#define SOAP_STR_PADDING (soap_padding) +#define SOAP_STR_EOS (soap_padding) +#define SOAP_NON_NULL (soap_padding) + +#ifndef WITH_LEAN +static const struct soap_code_map html_entity_codes[] = /* entities for XHTML parsing */ +{ { 160, "nbsp" }, + { 161, "iexcl" }, + { 162, "cent" }, + { 163, "pound" }, + { 164, "curren" }, + { 165, "yen" }, + { 166, "brvbar" }, + { 167, "sect" }, + { 168, "uml" }, + { 169, "copy" }, + { 170, "ordf" }, + { 171, "laquo" }, + { 172, "not" }, + { 173, "shy" }, + { 174, "reg" }, + { 175, "macr" }, + { 176, "deg" }, + { 177, "plusmn" }, + { 178, "sup2" }, + { 179, "sup3" }, + { 180, "acute" }, + { 181, "micro" }, + { 182, "para" }, + { 183, "middot" }, + { 184, "cedil" }, + { 185, "sup1" }, + { 186, "ordm" }, + { 187, "raquo" }, + { 188, "frac14" }, + { 189, "frac12" }, + { 190, "frac34" }, + { 191, "iquest" }, + { 192, "Agrave" }, + { 193, "Aacute" }, + { 194, "Acirc" }, + { 195, "Atilde" }, + { 196, "Auml" }, + { 197, "Aring" }, + { 198, "AElig" }, + { 199, "Ccedil" }, + { 200, "Egrave" }, + { 201, "Eacute" }, + { 202, "Ecirc" }, + { 203, "Euml" }, + { 204, "Igrave" }, + { 205, "Iacute" }, + { 206, "Icirc" }, + { 207, "Iuml" }, + { 208, "ETH" }, + { 209, "Ntilde" }, + { 210, "Ograve" }, + { 211, "Oacute" }, + { 212, "Ocirc" }, + { 213, "Otilde" }, + { 214, "Ouml" }, + { 215, "times" }, + { 216, "Oslash" }, + { 217, "Ugrave" }, + { 218, "Uacute" }, + { 219, "Ucirc" }, + { 220, "Uuml" }, + { 221, "Yacute" }, + { 222, "THORN" }, + { 223, "szlig" }, + { 224, "agrave" }, + { 225, "aacute" }, + { 226, "acirc" }, + { 227, "atilde" }, + { 228, "auml" }, + { 229, "aring" }, + { 230, "aelig" }, + { 231, "ccedil" }, + { 232, "egrave" }, + { 233, "eacute" }, + { 234, "ecirc" }, + { 235, "euml" }, + { 236, "igrave" }, + { 237, "iacute" }, + { 238, "icirc" }, + { 239, "iuml" }, + { 240, "eth" }, + { 241, "ntilde" }, + { 242, "ograve" }, + { 243, "oacute" }, + { 244, "ocirc" }, + { 245, "otilde" }, + { 246, "ouml" }, + { 247, "divide" }, + { 248, "oslash" }, + { 249, "ugrave" }, + { 250, "uacute" }, + { 251, "ucirc" }, + { 252, "uuml" }, + { 253, "yacute" }, + { 254, "thorn" }, + { 255, "yuml" }, + { 0, NULL } +}; +#endif + +#ifndef WITH_NOIO +#ifndef WITH_LEAN +static const struct soap_code_map h_error_codes[] = +{ +#ifdef HOST_NOT_FOUND + { HOST_NOT_FOUND, "Host not found" }, +#endif +#ifdef TRY_AGAIN + { TRY_AGAIN, "Try Again" }, +#endif +#ifdef NO_RECOVERY + { NO_RECOVERY, "No Recovery" }, +#endif +#ifdef NO_DATA + { NO_DATA, "No Data" }, +#endif +#ifdef NO_ADDRESS + { NO_ADDRESS, "No Address" }, +#endif + { 0, NULL } +}; +#endif +#endif + +#ifndef WITH_NOHTTP +#ifndef WITH_LEAN +static const struct soap_code_map h_http_error_codes[] = +{ { 201, "Created" }, + { 202, "Accepted" }, + { 203, "Non-Authoritative Information" }, + { 204, "No Content" }, + { 205, "Reset Content" }, + { 206, "Partial Content" }, + { 300, "Multiple Choices" }, + { 301, "Moved Permanently" }, + { 302, "Found" }, + { 303, "See Other" }, + { 304, "Not Modified" }, + { 305, "Use Proxy" }, + { 307, "Temporary Redirect" }, + { 400, "Bad Request" }, + { 401, "Unauthorized" }, + { 402, "Payment Required" }, + { 403, "Forbidden" }, + { 404, "Not Found" }, + { 405, "Method Not Allowed" }, + { 406, "Not Acceptable" }, + { 407, "Proxy Authentication Required" }, + { 408, "Request Time-out" }, + { 409, "Conflict" }, + { 410, "Gone" }, + { 411, "Length Required" }, + { 412, "Precondition Failed" }, + { 413, "Request Entity Too Large" }, + { 414, "Request-URI Too Large" }, + { 415, "Unsupported Media Type" }, + { 416, "Requested range not satisfiable" }, + { 417, "Expectation Failed" }, + { 500, "Internal Server Error" }, + { 501, "Not Implemented" }, + { 502, "Bad Gateway" }, + { 503, "Service Unavailable" }, + { 504, "Gateway Time-out" }, + { 505, "HTTP Version not supported" }, + { 0, NULL } +}; +#endif +#endif + +#ifdef WITH_OPENSSL +static const struct soap_code_map h_ssl_error_codes[] = +{ +#define _SSL_ERROR(e) { e, #e } + _SSL_ERROR(SSL_ERROR_SSL), + _SSL_ERROR(SSL_ERROR_ZERO_RETURN), + _SSL_ERROR(SSL_ERROR_WANT_READ), + _SSL_ERROR(SSL_ERROR_WANT_WRITE), + _SSL_ERROR(SSL_ERROR_WANT_CONNECT), + _SSL_ERROR(SSL_ERROR_WANT_X509_LOOKUP), + _SSL_ERROR(SSL_ERROR_SYSCALL), + { 0, NULL } +}; +#endif + +#ifndef WITH_LEANER +static const struct soap_code_map mime_codes[] = +{ { SOAP_MIME_7BIT, "7bit" }, + { SOAP_MIME_8BIT, "8bit" }, + { SOAP_MIME_BINARY, "binary" }, + { SOAP_MIME_QUOTED_PRINTABLE, "quoted-printable" }, + { SOAP_MIME_BASE64, "base64" }, + { SOAP_MIME_IETF_TOKEN, "ietf-token" }, + { SOAP_MIME_X_TOKEN, "x-token" }, + { 0, NULL } +}; +#endif + +#ifdef WIN32 +static int tcp_done = 0; +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +fsend(struct soap *soap, const char *s, size_t n) +{ register int nwritten; +#if defined(__cplusplus) && !defined(WITH_LEAN) + if (soap->os) + { soap->os->write(s, n); + if (soap->os->good()) + return SOAP_OK; + return SOAP_EOF; + } +#endif + while (n) + { if (soap_valid_socket(soap->socket)) + { +#ifndef WITH_LEAN + if (soap->send_timeout) + { struct timeval timeout; + fd_set fd; + if (soap->send_timeout > 0) + { timeout.tv_sec = soap->send_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->send_timeout/1000000; + timeout.tv_usec = -soap->send_timeout%1000000; + } + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->socket, &fd); + for (;;) + { register int r = select((SOAP_SOCKET)(soap->socket + 1), NULL, &fd, &fd, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + return SOAP_EOF; + } + if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EAGAIN) + { soap->errnum = soap_socket_errno; + return SOAP_EOF; + } + } + } +#endif +#ifdef WITH_OPENSSL + if (soap->ssl) + nwritten = SSL_write(soap->ssl, s, n); + else if (soap->bio) + nwritten = BIO_write(soap->bio, s, n); + else +#endif +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + { if (soap->peerlen) + nwritten = sendto((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags, (struct sockaddr*)&soap->peer, soap->peerlen); + else + nwritten = send((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags); + /* retry and back-off algorithm */ + /* TODO: this is not very clear from specs so verify and limit conditions under which we should loop (e.g. ENOBUFS) */ + if (nwritten < 0) + { struct timeval timeout; + fd_set fd; + int udp_repeat; + int udp_delay; + if ((soap->connect_flags & SO_BROADCAST)) + udp_repeat = 3; /* SOAP-over-UDP MULTICAST_UDP_REPEAT - 1 */ + else + udp_repeat = 1; /* SOAP-over-UDP UNICAST_UDP_REPEAT - 1 */ + udp_delay = (soap_random % 201) + 50; /* UDP_MIN_DELAY .. UDP_MAX_DELAY */ + do + { timeout.tv_sec = 0; + timeout.tv_usec = 1000 * udp_delay; /* ms */ + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->socket, &fd); + select((SOAP_SOCKET)(soap->socket + 1), NULL, NULL, &fd, &timeout); + if (soap->peerlen) + nwritten = sendto((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags, (struct sockaddr*)&soap->peer, soap->peerlen); + else + nwritten = send((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags); + udp_delay <<= 1; + if (udp_delay > 500) /* UDP_UPPER_DELAY */ + udp_delay = 500; + } + while (nwritten < 0 && --udp_repeat > 0); + } + } + else +#endif +#ifndef PALM + nwritten = send((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags); +#else + nwritten = send((SOAP_SOCKET)soap->socket, (void*)s, n, soap->socket_flags); +#endif + if (nwritten <= 0) + { +#ifdef WITH_OPENSSL + int err; + if (soap->ssl && (err = SSL_get_error(soap->ssl, nwritten)) != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) + return SOAP_EOF; +#endif + if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EWOULDBLOCK && soap_socket_errno != SOAP_EAGAIN) + { soap->errnum = soap_socket_errno; + return SOAP_EOF; + } + nwritten = 0; /* and call write() again */ + } + } + else + { +#ifdef WITH_FASTCGI + nwritten = fwrite((void*)s, 1, n, stdout); + fflush(stdout); +#else +#ifdef UNDER_CE + nwritten = fwrite(s, 1, n, soap->sendfd); +#else +#ifdef VXWORKS +#ifdef WMW_RPM_IO + if (soap->rpmreqid) + nwritten = (httpBlockPut(soap->rpmreqid, s, n) == 0) ? n : -1; + else + nwritten = fwrite(s, sizeof(char), n, fdopen(soap->sendfd, "w")); +#else + nwritten = fwrite(s, sizeof(char), n, fdopen(soap->sendfd, "w")); +#endif /* WMW_RPM_IO */ +#else + nwritten = write((SOAP_SOCKET)soap->sendfd, s, n); +#endif +#endif +#endif + if (nwritten <= 0) + { if (soap_errno != SOAP_EINTR && soap_errno != SOAP_EWOULDBLOCK && soap_errno != SOAP_EAGAIN) + { soap->errnum = soap_errno; + return SOAP_EOF; + } + nwritten = 0; /* and call write() again */ + } + } + n -= nwritten; + s += nwritten; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send_raw(struct soap *soap, const char *s, size_t n) +{ if (!n) + return SOAP_OK; + if (soap->mode & SOAP_IO_LENGTH) + { soap->count += n; +#ifndef WITH_LEANER + if (soap->fpreparesend && (soap->mode & SOAP_IO) != SOAP_IO_STORE) + return soap->error = soap->fpreparesend(soap, s, n); +#endif + return SOAP_OK; + } + if (soap->mode & SOAP_IO) + { register size_t i = SOAP_BUFLEN - soap->bufidx; + while (n >= i) + { memcpy(soap->buf + soap->bufidx, s, i); + soap->bufidx = SOAP_BUFLEN; + if (soap_flush(soap)) + return soap->error; + s += i; + n -= i; + i = SOAP_BUFLEN; + } + memcpy(soap->buf + soap->bufidx, s, n); + soap->bufidx += n; + return SOAP_OK; + } + return soap_flush_raw(soap, s, n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_flush(struct soap *soap) +{ register int n = soap->bufidx; + if (n) + { soap->bufidx = 0; +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { soap->d_stream.next_in = (Byte*)soap->buf; + soap->d_stream.avail_in = (unsigned int)n; +#ifdef WITH_GZIP + soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)n); +#endif + do + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating %u bytes\n", soap->d_stream.avail_in)); + if (deflate(&soap->d_stream, Z_NO_FLUSH) != Z_OK) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to deflate: %s\n", soap->d_stream.msg?soap->d_stream.msg:"")); + return soap->error = SOAP_ZLIB_ERROR; + } + if (!soap->d_stream.avail_out) + { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN)) + return soap->error; + soap->d_stream.next_out = (Byte*)soap->z_buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + } + } while (soap->d_stream.avail_in); + } + else +#endif + return soap_flush_raw(soap, soap->buf, n); + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_flush_raw(struct soap *soap, const char *s, size_t n) +{ if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) + { register char *t; + if (!(t = (char*)soap_push_block(soap, n))) + return soap->error = SOAP_EOM; + memcpy(t, s, n); +#ifndef WITH_LEANER + if (soap->fpreparesend) + return soap->error = soap->fpreparesend(soap, s, n); +#endif + return SOAP_OK; + } +#ifndef WITH_LEANER + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) + { char t[16]; + sprintf(t, "\r\n%lX\r\n" + (soap->chunksize ? 0 : 2), (unsigned long)n); + DBGMSG(SENT, t, strlen(t)); + if ((soap->error = soap->fsend(soap, t, strlen(t)))) + return soap->error; + soap->chunksize += n; + } + DBGMSG(SENT, s, n); +#endif + return soap->error = soap->fsend(soap, s, n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send(struct soap *soap, const char *s) +{ if (s) + return soap_send_raw(soap, s, strlen(s)); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send2(struct soap *soap, const char *s1, const char *s2) +{ if (soap_send(soap, s1)) + return soap->error; + return soap_send(soap, s2); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send3(struct soap *soap, const char *s1, const char *s2, const char *s3) +{ if (soap_send(soap, s1) + || soap_send(soap, s2)) + return soap->error; + return soap_send(soap, s3); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static size_t +frecv(struct soap *soap, char *s, size_t n) +{ register int r; + soap->errnum = 0; +#if defined(__cplusplus) && !defined(WITH_LEAN) + if (soap->is) + { if (soap->is->good()) + return soap->is->read(s, n).gcount(); + return 0; + } +#endif + if (soap_valid_socket(soap->socket)) + { for (;;) + { +#ifndef WITH_LEAN + if (soap->recv_timeout) + { struct timeval timeout; + fd_set fd; + if (soap->recv_timeout > 0) + { timeout.tv_sec = soap->recv_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->recv_timeout/1000000; + timeout.tv_usec = -soap->recv_timeout%1000000; + } + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->socket, &fd); + for (;;) + { r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + return 0; + } + if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EAGAIN) + { soap->errnum = soap_socket_errno; + return 0; + } + } + } +#endif +#ifdef WITH_OPENSSL + if (soap->ssl) + { int err; + r = SSL_read(soap->ssl, s, n); + if (r > 0) + return (size_t)r; + err = SSL_get_error(soap->ssl, r); + if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) + return 0; + } + else if (soap->bio) + { r = BIO_read(soap->bio, s, n); + if (r > 0) + return (size_t)r; + return 0; + } + else +#endif + { +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + { SOAP_SOCKLEN_T k = (SOAP_SOCKLEN_T)sizeof(soap->peer); + memset((void*)&soap->peer, 0, sizeof(soap->peer)); + r = recvfrom((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags, (struct sockaddr*)&soap->peer, &k); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */ + soap->peerlen = (size_t)k; +#ifndef WITH_IPV6 + soap->ip = ntohl(soap->peer.sin_addr.s_addr); + soap->port = (int)ntohs(soap->peer.sin_port); +#endif + } + else +#endif + r = recv((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags); + if (r >= 0) + return (size_t)r; + if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EAGAIN && soap_socket_errno != SOAP_EWOULDBLOCK) + { soap->errnum = soap_socket_errno; + return 0; + } + } +#ifndef WITH_LEAN + { struct timeval timeout; + fd_set fd; + timeout.tv_sec = 0; + timeout.tv_usec = 10000; + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->socket, &fd); +#ifdef WITH_OPENSSL + if (soap->ssl && SSL_get_error(soap->ssl, r) == SSL_ERROR_WANT_WRITE) + r = select((SOAP_SOCKET)(soap->socket + 1), NULL, &fd, &fd, &timeout); + else + r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout); +#else + r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout); +#endif + if (r < 0 && soap_socket_errno != SOAP_EINTR) + { soap->errnum = soap_socket_errno; + return 0; + } + } +#endif + } + } +#ifdef WITH_FASTCGI + return fread(s, 1, n, stdin); +#else +#ifdef UNDER_CE + return fread(s, 1, n, soap->recvfd); +#else +#ifdef WMW_RPM_IO + if (soap->rpmreqid) + r = httpBlockRead(soap->rpmreqid, s, n); +#endif + r = read((SOAP_SOCKET)soap->recvfd, s, n); + if (r >= 0) + return (size_t)r; + soap->errnum = soap_errno; + return 0; +#endif +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static soap_wchar +soap_getchunkchar(struct soap *soap) +{ if (soap->bufidx < soap->buflen) + return soap->buf[soap->bufidx++]; + soap->bufidx = 0; + soap->buflen = soap->chunkbuflen = soap->frecv(soap, soap->buf, SOAP_BUFLEN); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket %d\n", (unsigned int)soap->buflen, soap->socket)); + DBGMSG(RECV, soap->buf, soap->buflen); + if (soap->buflen) + return soap->buf[soap->bufidx++]; + return EOF; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +soap_isxdigit(int c) +{ return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv_raw(struct soap *soap) +{ register size_t ret; +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { if (soap->d_stream.next_out == Z_NULL) + return EOF; + if (soap->d_stream.avail_in || !soap->d_stream.avail_out) + { register int r; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflating\n")); + soap->d_stream.next_out = (Byte*)soap->buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + r = inflate(&soap->d_stream, Z_NO_FLUSH); + if (r == Z_OK || r == Z_STREAM_END) + { soap->bufidx = 0; + soap->buflen = SOAP_BUFLEN - soap->d_stream.avail_out; + if (soap->zlib_in == SOAP_ZLIB_GZIP) + soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen); + if (r == Z_STREAM_END) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out)); + soap->z_ratio_in = (float)soap->d_stream.total_in / (float)soap->d_stream.total_out; + soap->d_stream.next_out = Z_NULL; + } + if (soap->buflen) + { soap->count += soap->buflen; + return SOAP_OK; + } + } + else if (r != Z_BUF_ERROR) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate error: %s\n", soap->d_stream.msg?soap->d_stream.msg:"")); + soap->d_stream.next_out = Z_NULL; + soap->error = SOAP_ZLIB_ERROR; + return EOF; + } + } +zlib_again: + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK && !soap->chunksize) + { memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN); + soap->buflen = soap->z_buflen; + } + } +#endif +#ifndef WITH_NOHTTP + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) /* read HTTP chunked transfer */ + { +chunk_again: + if (soap->chunksize) + { soap->buflen = ret = soap->frecv(soap, soap->buf, soap->chunksize > SOAP_BUFLEN ? SOAP_BUFLEN : soap->chunksize); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk: read %u bytes\n", (unsigned int)ret)); + DBGMSG(RECV, soap->buf, ret); + soap->bufidx = 0; + soap->chunksize -= ret; + } + else + { register soap_wchar c; + char *t, tmp[8]; + t = tmp; + if (!soap->chunkbuflen) + { soap->chunkbuflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes (chunked) from socket %d\n", (unsigned int)ret, soap->socket)); + DBGMSG(RECV, soap->buf, ret); + soap->bufidx = 0; + if (!ret) + return soap->ahead = EOF; + } + else + soap->bufidx = soap->buflen; + soap->buflen = soap->chunkbuflen; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk size (idx=%u len=%u)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen)); + while (!soap_isxdigit((int)(c = soap_getchunkchar(soap)))) + if ((int)c == EOF) + return soap->ahead = EOF; + do + *t++ = (char)c; + while (soap_isxdigit((int)(c = soap_getchunkchar(soap))) && t - tmp < 7); + while ((int)c != EOF && c != '\n') + c = soap_getchunkchar(soap); + if ((int)c == EOF) + return soap->ahead = EOF; + *t = '\0'; + soap->chunksize = soap_strtoul(tmp, &t, 16); + if (!soap->chunksize) + { soap->chunkbuflen = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of chunked message\n")); + while ((int)c != EOF && c != '\n') + c = soap_getchunkchar(soap); + return soap->ahead = EOF; + } + soap->buflen = soap->bufidx + soap->chunksize; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving buf len to idx=%u len=%u (%s)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen, tmp)); + if (soap->buflen > soap->chunkbuflen) + { soap->buflen = soap->chunkbuflen; + soap->chunksize -= soap->buflen - soap->bufidx; + soap->chunkbuflen = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Passed end of buffer for chunked HTTP (%u bytes left)\n", (unsigned int)(soap->buflen - soap->bufidx))); + } + else if (soap->chunkbuflen) + soap->chunksize = 0; + ret = soap->buflen - soap->bufidx; + if (!ret) + goto chunk_again; + } + } + else +#endif + { soap->bufidx = 0; + soap->buflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket %d\n", (unsigned int)ret, soap->socket)); + DBGMSG(RECV, soap->buf, ret); + } +#ifndef WITH_LEANER + if (soap->fpreparerecv && (soap->error = soap->fpreparerecv(soap, soap->buf, ret))) + return soap->error; +#endif +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { register int r; + memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); + soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx); + soap->d_stream.avail_in = (unsigned int)ret; + soap->d_stream.next_out = (Byte*)soap->buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + r = inflate(&soap->d_stream, Z_NO_FLUSH); + if (r == Z_OK || r == Z_STREAM_END) + { soap->bufidx = 0; + soap->z_buflen = soap->buflen; + soap->buflen = ret = SOAP_BUFLEN - soap->d_stream.avail_out; + if (soap->zlib_in == SOAP_ZLIB_GZIP) + soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %u bytes\n", (unsigned int)ret)); + if (!ret) + goto zlib_again; + if (r == Z_STREAM_END) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out)); + soap->z_ratio_in = (float)soap->d_stream.total_in / (float)soap->d_stream.total_out; + soap->d_stream.next_out = Z_NULL; + } + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to inflate: (%d) %s\n", r, soap->d_stream.msg?soap->d_stream.msg:"")); + soap->d_stream.next_out = Z_NULL; + soap->error = SOAP_ZLIB_ERROR; + return EOF; + } + } +#endif + soap->count += ret; + return !ret; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv(struct soap *soap) +{ +#ifndef WITH_LEANER + if (soap->mode & SOAP_ENC_DIME) + { if (soap->dime.buflen) + { char *s; + int i; + unsigned char tmp[12]; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME hdr for chunked DIME is in buffer\n")); + soap->count += soap->dime.buflen - soap->buflen; + soap->buflen = soap->dime.buflen; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Skip padding (%ld bytes)\n", -(long)soap->dime.size&3)); + for (i = -(long)soap->dime.size&3; i > 0; i--) + { soap->bufidx++; + if (soap->bufidx >= soap->buflen) + if (soap_recv_raw(soap)) + return EOF; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME hdr for next chunk\n")); + s = (char*)tmp; + for (i = 12; i > 0; i--) + { *s++ = soap->buf[soap->bufidx++]; + if (soap->bufidx >= soap->buflen) + if (soap_recv_raw(soap)) + return EOF; + } + soap->dime.flags = tmp[0] & 0x7; + soap->dime.size = ((size_t)tmp[8] << 24) | ((size_t)tmp[9] << 16) | ((size_t)tmp[10] << 8) | ((size_t)tmp[11]); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME chunk (%u bytes)\n", (unsigned int)soap->dime.size)); + if (soap->dime.flags & SOAP_DIME_CF) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "More chunking\n")); + soap->dime.chunksize = soap->dime.size; + if (soap->buflen - soap->bufidx >= soap->dime.size) + { soap->dime.buflen = soap->buflen; + soap->buflen = soap->bufidx + soap->dime.chunksize; + } + else + soap->dime.chunksize -= soap->buflen - soap->bufidx; + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Last chunk\n")); + soap->dime.buflen = 0; + soap->dime.chunksize = 0; + } + soap->count = soap->buflen - soap->bufidx; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%u bytes remaining\n", (unsigned int)soap->count)); + return SOAP_OK; + } + if (soap->dime.chunksize) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get next DIME hdr for chunked DIME (%u bytes chunk)\n", (unsigned int)soap->dime.chunksize)); + if (soap_recv_raw(soap)) + return EOF; + if (soap->buflen - soap->bufidx >= soap->dime.chunksize) + { soap->dime.buflen = soap->buflen; + soap->count -= soap->buflen - soap->bufidx - soap->dime.chunksize; + soap->buflen = soap->bufidx + soap->dime.chunksize; + } + else + soap->dime.chunksize -= soap->buflen - soap->bufidx; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%lu bytes remaining, count=%u\n", (unsigned long)(soap->buflen-soap->bufidx), (unsigned int)soap->count)); + return SOAP_OK; + } + } +#endif + return soap_recv_raw(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +soap_wchar +SOAP_FMAC2 +soap_getchar(struct soap *soap) +{ register soap_wchar c; + c = soap->ahead; + if (c) + { if (c != EOF) + soap->ahead = 0; + return c; + } + return soap_get1(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +const struct soap_code_map* +SOAP_FMAC2 +soap_code(const struct soap_code_map *map, const char *str) +{ if (str) + { while (map->string) + { if (!strcmp(str, map->string)) /* case sensitive */ + return map; + map++; + } + } + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +long +SOAP_FMAC2 +soap_int_code(const struct soap_code_map *map, const char *str, long other) +{ while (map->string) + { if (!soap_tag_cmp(str, map->string)) /* case insensitive */ + return map->code; + map++; + } + return other; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_str_code(const struct soap_code_map *map, long code) +{ while (map->code != code && map->string) + map++; + return map->string; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static soap_wchar +soap_char(struct soap *soap) +{ char tmp[8]; + register int i; + register soap_wchar c; + register char *s = tmp; + for (i = 0; i < 7; i++) + { c = soap_get1(soap); + if (c == ';' || (int)c == EOF) + break; + *s++ = (char)c; + } + *s = '\0'; + if (*tmp == '#') + { if (tmp[1] == 'x' || tmp[1] == 'X') + return soap_strtol(tmp + 2, NULL, 16); + return atol(tmp + 1); + } + if (!strcmp(tmp, "lt")) + return '<'; + if (!strcmp(tmp, "gt")) + return '>'; + if (!strcmp(tmp, "amp")) + return '&'; + if (!strcmp(tmp, "quot")) + return '"'; + if (!strcmp(tmp, "apos")) + return '\''; +#ifndef WITH_LEAN + return (soap_wchar)soap_int_code(html_entity_codes, tmp, SOAP_UNKNOWN_CHAR); +#else + return SOAP_UNKNOWN_CHAR; /* use this to represent unknown code */ +#endif +} +#endif + +/******************************************************************************/ +#ifdef WITH_LEAN +soap_wchar +soap_get0(struct soap *soap) +{ if (soap->bufidx >= soap->buflen && soap_recv(soap)) + return EOF; + return (unsigned char)soap->buf[soap->bufidx]; +} +#endif + +/******************************************************************************/ +#ifdef WITH_LEAN +soap_wchar +soap_get1(struct soap *soap) +{ if (soap->bufidx >= soap->buflen && soap_recv(soap)) + return EOF; + return (unsigned char)soap->buf[soap->bufidx++]; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +soap_wchar +SOAP_FMAC2 +soap_get(struct soap *soap) +{ register soap_wchar c; + c = soap->ahead; + if (c) + { if (c != EOF) + soap->ahead = 0; + } + else + c = soap_get1(soap); + for (;;) + { if (soap->cdata) + { if (c == ']') + { c = soap_get1(soap); + if (c == ']') + { soap->cdata = 0; + soap_get1(soap); /* skip > */ + c = soap_get1(soap); + } + else + { soap_revget1(soap); + return ']'; + } + } + else + return c; + } + switch (c) + { case '<': + do c = soap_get1(soap); + while (soap_blank(c)); + if (c == '!' || c == '?' || c == '%') + { register int k = 1; + if (c == '!') + { c = soap_get1(soap); + if (c == '[') + { do c = soap_get1(soap); + while ((int)c != EOF && c != '['); + if ((int)c == EOF) + break; + soap->cdata = 1; + c = soap_get1(soap); + continue; + } + if (c == '-' && (c = soap_get1(soap)) == '-') + { do + { c = soap_get1(soap); + if (c == '-' && (c = soap_get1(soap)) == '-') + break; + } while ((int)c != EOF); + } + } + while ((int)c != EOF) + { if (c == '<') + k++; + else if (c == '>') + { if (--k <= 0) + break; + } + c = soap_get1(soap); + } + if ((int)c == EOF) + break; + c = soap_get1(soap); + continue; + } + if (c == '/') + return SOAP_TT; + soap_revget1(soap); + return SOAP_LT; + case '>': + return SOAP_GT; + case '"': + return SOAP_QT; + case '\'': + return SOAP_AP; + case '&': + return soap_char(soap) | 0x80000000; + } + break; + } + return c; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_move(struct soap *soap, long n) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving %ld bytes forward\n", (long)n)); + for (; n > 0; n--) + if ((int)soap_getchar(soap) == EOF) + return SOAP_EOF; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_tell(struct soap *soap) +{ return soap->count - soap->buflen + soap->bufidx - (soap->ahead != 0); +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_pututf8(struct soap *soap, register unsigned long c) +{ char tmp[16]; + if (c > 0 && c < 0x80) + { *tmp = (char)c; + return soap_send_raw(soap, tmp, 1); + } +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { register char *t = tmp; + if (c < 0x0800) + *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); + else + { if (c < 0x010000) + *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + else + { if (c < 0x200000) + *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + else + { if (c < 0x04000000) + *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + else + { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + } + *t++ = (char)(0x80 | (c & 0x3F)); + *t = '\0'; + } + else +#endif + sprintf(tmp, "&#%lu;", c); + return soap_send(soap, tmp); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +soap_wchar +SOAP_FMAC2 +soap_getutf8(struct soap *soap) +{ register soap_wchar c, c1, c2, c3, c4; + c = soap_get(soap); + if (c < 0x80 || (soap->mode & SOAP_ENC_LATIN)) + return c; + c1 = soap_get(soap); + if (c1 < 0x80) + { soap_unget(soap, c1); + return c; + } + c1 &= 0x3F; + if (c < 0xE0) + return ((soap_wchar)(c & 0x1F) << 6) | c1; + c2 = (soap_wchar)soap_get1(soap) & 0x3F; + if (c < 0xF0) + return ((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2; + c3 = (soap_wchar)soap_get1(soap) & 0x3F; + if (c < 0xF8) + return ((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3; + c4 = (soap_wchar)soap_get1(soap) & 0x3F; + if (c < 0xFC) + return ((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4; + return ((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(soap_get1(soap) & 0x3F); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_puthex(struct soap *soap, const unsigned char *s, int n) +{ char d[2]; + register int i; +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { if (!(soap->dom->data = soap_s2hex(soap, s, NULL, n))) + return soap->error; + return SOAP_OK; + } +#endif + for (i = 0; i < n; i++) + { register int m = *s++; + d[0] = (char)((m >> 4) + (m > 159 ? '7' : '0')); + m &= 0x0F; + d[1] = (char)(m + (m > 9 ? '7' : '0')); + if (soap_send_raw(soap, d, 2)) + return soap->error; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +unsigned char* +SOAP_FMAC2 +soap_gethex(struct soap *soap, int *n) +{ +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { soap->dom->data = soap_string_in(soap, 0, -1, -1); + return (unsigned char*)soap_hex2s(soap, soap->dom->data, NULL, 0, n); + } +#endif +#ifdef WITH_FAST + soap->labidx = 0; + for (;;) + { register char *s; + register int i, k; + if (soap_append_lab(soap, NULL, 0)) + return NULL; + s = soap->labbuf + soap->labidx; + k = soap->lablen - soap->labidx; + soap->labidx = soap->lablen; + for (i = 0; i < k; i++) + { register char d1, d2; + register soap_wchar c; + c = soap_get(soap); + if (soap_isxdigit(c)) + { d1 = (char)c; + c = soap_get(soap); + if (soap_isxdigit(c)) + d2 = (char)c; + else + { soap->error = SOAP_TYPE; + return NULL; + } + } + else + { unsigned char *p; + soap_unget(soap, c); + if (n) + *n = (int)(soap->lablen - k + i); + p = (unsigned char*)soap_malloc(soap, soap->lablen - k + i); + if (p) + memcpy(p, soap->labbuf, soap->lablen - k + i); + return p; + } + *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'); + } + } +#else + if (soap_new_block(soap)) + return NULL; + for (;;) + { register int i; + register char *s = (char*)soap_push_block(soap, SOAP_BLKLEN); + if (!s) + { soap_end_block(soap); + return NULL; + } + for (i = 0; i < SOAP_BLKLEN; i++) + { register char d1, d2; + register soap_wchar c = soap_get(soap); + if (soap_isxdigit(c)) + { d1 = (char)c; + c = soap_get(soap); + if (soap_isxdigit(c)) + d2 = (char)c; + else + { soap_end_block(soap); + soap->error = SOAP_TYPE; + return NULL; + } + } + else + { unsigned char *p; + soap_unget(soap, c); + if (n) + *n = soap_size_block(soap, i); + p = (unsigned char*)soap_save_block(soap, NULL, 0); + return p; + } + *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'); + } + } +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putbase64(struct soap *soap, const unsigned char *s, int n) +{ register int i; + register unsigned long m; + char d[4]; + if (!s) + return SOAP_OK; +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { if (!(soap->dom->data = soap_s2base64(soap, s, NULL, n))) + return soap->error; + return SOAP_OK; + } +#endif + for (; n > 2; n -= 3, s += 3) + { m = s[0]; + m = (m << 8) | s[1]; + m = (m << 8) | s[2]; + for (i = 4; i > 0; m >>= 6) + d[--i] = soap_base64o[m & 0x3F]; + if (soap_send_raw(soap, d, 4)) + return soap->error; + } + if (n > 0) + { m = 0; + for (i = 0; i < n; i++) + m = (m << 8) | *s++; + for (; i < 3; i++) + m <<= 8; + for (i++; i > 0; m >>= 6) + d[--i] = soap_base64o[m & 0x3F]; + for (i = 3; i > n; i--) + d[i] = '='; + if (soap_send_raw(soap, d, 4)) + return soap->error; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +unsigned char* +SOAP_FMAC2 +soap_getbase64(struct soap *soap, int *n, int malloc_flag) +{ +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { soap->dom->data = soap_string_in(soap, 0, -1, -1); + return (unsigned char*)soap_base642s(soap, soap->dom->data, NULL, 0, n); + } +#endif +#ifdef WITH_FAST + soap->labidx = 0; + for (;;) + { register int i, k; + register char *s; + if (soap_append_lab(soap, NULL, 2)) + return NULL; + s = soap->labbuf + soap->labidx; + k = 3 * ((soap->lablen - soap->labidx) / 3); + soap->labidx = 3 * (soap->lablen / 3); + if (!s) + return NULL; + for (i = 0; i < k; i += 3) + { register unsigned long m = 0; + register int j = 0; + do + { register soap_wchar c = soap_get(soap); + if (c == '=' || c < 0) + { unsigned char *p; + switch (j) + { case 2: + *s++ = (char)((m >> 4) & 0xFF); + i++; + break; + case 3: + *s++ = (char)((m >> 10) & 0xFF); + *s++ = (char)((m >> 2) & 0xFF); + i += 2; + } + if (n) + *n = (int)(soap->lablen - k + i - 1); + p = (unsigned char*)soap_malloc(soap, soap->lablen - k + i - 1); + if (p) + memcpy(p, soap->labbuf, soap->lablen - k + i - 1); + if (c >= 0) + { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT) + ; + } + soap_unget(soap, c); + return p; + } + c -= '+'; + if (c >= 0 && c <= 79) + { m = (m << 6) + soap_base64i[c]; + j++; + } + } while (j < 4); + *s++ = (char)((m >> 16) & 0xFF); + *s++ = (char)((m >> 8) & 0xFF); + *s++ = (char)(m & 0xFF); + } + } +#else + if (soap_new_block(soap)) + return NULL; + for (;;) + { register int i; + register char *s = (char*)soap_push_block(soap, 3 * SOAP_BLKLEN); /* must be multiple of 3 */ + if (!s) + { soap_end_block(soap); + return NULL; + } + for (i = 0; i < SOAP_BLKLEN; i++) + { register unsigned long m = 0; + register int j = 0; + do + { register soap_wchar c = soap_get(soap); + if (c == '=' || c < 0) + { unsigned char *p; + i *= 3; + switch (j) + { case 2: + *s++ = (char)((m >> 4) & 0xFF); + i++; + break; + case 3: + *s++ = (char)((m >> 10) & 0xFF); + *s++ = (char)((m >> 2) & 0xFF); + i += 2; + } + if (n) + *n = (int)soap_size_block(soap, i); + p = (unsigned char*)soap_save_block(soap, NULL, 0); + if (c >= 0) + { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT) + ; + } + soap_unget(soap, c); + return p; + } + c -= '+'; + if (c >= 0 && c <= 79) + { m = (m << 6) + soap_base64i[c]; + j++; + } + } while (j < 4); + *s++ = (char)((m >> 16) & 0xFF); + *s++ = (char)((m >> 8) & 0xFF); + *s++ = (char)(m & 0xFF); + } + } +#endif +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_xop_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options) +{ /* Check MTOM xop:Include element (within hex/base64Binary) */ + /* TODO: this code to be obsoleted with new import/xop.h conventions */ + int body = soap->body; /* should save type too? */ + if (!soap_peek_element(soap)) + { if (!soap_element_begin_in(soap, "xop:Include", 0) && *soap->href) + { if (soap_dime_forward(soap, ptr, size, id, type, options)) + return soap->error; + } + if (soap->body && soap_element_end_in(soap, NULL)) + return soap->error; + } + soap->body = body; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_dime_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options) +{ struct soap_xlist *xp = (struct soap_xlist*)SOAP_MALLOC(soap, sizeof(struct soap_xlist)); + *ptr = NULL; + *size = 0; + *id = soap_strdup(soap, soap->href); + *type = NULL; + *options = NULL; + if (!xp) + return soap->error = SOAP_EOM; + xp->next = soap->xlist; + xp->ptr = ptr; + xp->size = size; + xp->id = *id; + xp->type = type; + xp->options = options; + soap->xlist = xp; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_strdup(struct soap *soap, const char *s) +{ char *t = NULL; + if (s && (t = (char*)soap_malloc(soap, strlen(s) + 1))) + strcpy(t, s); + return t; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_new_block(struct soap *soap) +{ struct soap_blist *p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New block sequence (prev=%p)\n", soap->blist)); + if (!(p = (struct soap_blist*)SOAP_MALLOC(soap, sizeof(struct soap_blist)))) + return SOAP_EOM; + p->next = soap->blist; + p->ptr = NULL; + p->size = 0; + soap->blist = p; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_push_block(struct soap *soap, size_t n) +{ char *p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push block of %u bytes (%u bytes total)\n", (unsigned int)n, (unsigned int)soap->blist->size + (unsigned int)n)); + if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(char*) + sizeof(size_t)))) + { soap->error = SOAP_EOM; + return NULL; + } + *(char**)p = soap->blist->ptr; + *(size_t*)(p + sizeof(char*)) = n; + soap->blist->ptr = p; + soap->blist->size += n; + return p + sizeof(char*) + sizeof(size_t); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_pop_block(struct soap *soap) +{ char *p; + if (!soap->blist->ptr) + return; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop block\n")); + p = soap->blist->ptr; + soap->blist->size -= *(size_t*)(p + sizeof(char*)); + soap->blist->ptr = *(char**)p; + SOAP_FREE(soap, p); +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static void +soap_update_ptrs(struct soap *soap, char *start, char *end, long offset) +{ int i; + register struct soap_ilist *ip; + register struct soap_flist *fp; +#ifndef WITH_LEANER + register struct soap_xlist *xp; +#endif + register void *p, **q; + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { if (ip->ptr && (char*)ip->ptr >= start && (char*)ip->ptr < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", ip->id, ip->ptr, (char*)ip->ptr + offset)); + ip->ptr = (char*)ip->ptr + offset; + } + for (q = &ip->link; q; q = (void**)p) + { p = *q; + if (p && (char*)p >= start && (char*)p < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Link update id='%s' %p\n", ip->id, p)); + *q = (char*)p + offset; + } + } + for (q = &ip->copy; q; q = (void**)p) + { p = *q; + if (p && (char*)p >= start && (char*)p < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy chain update id='%s' %p\n", ip->id, p)); + *q = (char*)p + offset; + } + } + for (fp = ip->flist; fp; fp = fp->next) + { if ((char*)fp->ptr >= start && (char*)fp->ptr < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy list update id='%s' %p\n", ip->id, fp)); + fp->ptr = (char*)fp->ptr + offset; + } + } + } + } +#ifndef WITH_LEANER + for (xp = soap->xlist; xp; xp = xp->next) + { if (xp->ptr && (char*)xp->ptr >= start && (char*)xp->ptr < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", xp->id?xp->id:"", xp->ptr, (char*)xp->ptr + offset)); + xp->ptr = (unsigned char**)((char*)xp->ptr + offset); + xp->size = (int*)((char*)xp->size + offset); + xp->type = (char**)((char*)xp->type + offset); + xp->options = (char**)((char*)xp->options + offset); + } + } +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static int +soap_has_copies(struct soap *soap, register const char *start, register const char *end) +{ register int i; + register struct soap_ilist *ip; + register struct soap_flist *fp; + register const char *p; + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { for (p = (const char*)ip->copy; p; p = *(const char**)p) + if (p >= start && p < end) + return SOAP_ERR; + for (fp = ip->flist; fp; fp = fp->next) + if ((const char*)fp->ptr >= start && (const char*)fp->ptr < end) + return SOAP_ERR; + } + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_resolve(struct soap *soap) +{ register int i; + register struct soap_ilist *ip; + register struct soap_flist *fp; + short flag; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data\n")); + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { if (ip->ptr) + { register void *p, **q, *r; + q = (void**)ip->link; + ip->link = NULL; + r = ip->ptr; + DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing link chain to resolve id='%s'\n", ip->id)); + while (q) + { p = *q; + *q = r; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "... link %p -> %p\n", q, r)); + q = (void**)p; + } + } + else if (*ip->id == '#') + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Missing data for id='%s'\n", ip->id)); + strcpy(soap->id, ip->id + 1); + return soap->error = SOAP_MISSING_ID; + } + } + } + do + { flag = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution phase\n")); + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { if (ip->ptr && !soap_has_copies(soap, (const char*)ip->ptr, (const char*)ip->ptr + ip->size)) + { if (ip->copy) + { register void *p, **q = (void**)ip->copy; + DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing copy chain to resolve id='%s'\n", ip->id)); + ip->copy = NULL; + do + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... copy %p -> %p (%u bytes)\n", ip->ptr, q, (unsigned int)ip->size)); + p = *q; + memcpy(q, ip->ptr, ip->size); + q = (void**)p; + } while (q); + flag = 1; + } + for (fp = ip->flist; fp; fp = ip->flist) + { register unsigned int k = fp->level; + register void *p = ip->ptr; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data type=%d location=%p level=%u,%u id='%s'\n", ip->type, p, ip->level, fp->level, ip->id)); + while (ip->level < k) + { register void **q = (void**)soap_malloc(soap, sizeof(void*)); + if (!q) + return soap->error; + *q = p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level, new location=%p holds=%p...\n", q, *q)); + p = (void*)q; + k--; + } + if (fp->fcopy) + fp->fcopy(soap, ip->type, fp->type, fp->ptr, p, ip->size); + else + soap_fcopy(soap, ip->type, fp->type, fp->ptr, p, ip->size); + ip->flist = fp->next; + SOAP_FREE(soap, fp); + flag = 1; + } + } + } + } + } while (flag); +#ifdef SOAP_DEBUG + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { if (ip->copy || ip->flist) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution error: forwarded data for id='%s' could not be propagated, please report this problem to the developers\n", ip->id)); + } + } + } +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution done\n")); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_size_block(struct soap *soap, size_t n) +{ if (soap->blist->ptr) + { soap->blist->size -= *(size_t*)(soap->blist->ptr + sizeof(char*)) - n; + *(size_t*)(soap->blist->ptr + sizeof(char*)) = n; + } + return soap->blist->size; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_first_block(struct soap *soap) +{ char *p, *q, *r; + p = soap->blist->ptr; + if (!p) + return NULL; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "First block\n")); + r = NULL; + do + { q = *(char**)p; + *(char**)p = r; + r = p; + p = q; + } while (p); + soap->blist->ptr = r; + return r + sizeof(char*) + sizeof(size_t); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_next_block(struct soap *soap) +{ char *p; + p = soap->blist->ptr; + if (p) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Next block\n")); + soap->blist->ptr = *(char**)p; + SOAP_FREE(soap, p); + if (soap->blist->ptr) + return soap->blist->ptr + sizeof(char*) + sizeof(size_t); + } + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_block_size(struct soap *soap) +{ return *(size_t*)(soap->blist->ptr + sizeof(char*)); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_end_block(struct soap *soap) +{ struct soap_blist *bp; + char *p, *q; + bp = soap->blist; + if (bp) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of block sequence, free all remaining blocks\n")); + for (p = bp->ptr; p; p = q) + { q = *(char**)p; + SOAP_FREE(soap, p); + } + soap->blist = bp->next; + SOAP_FREE(soap, bp); + } + DBGLOG(TEST, if (soap->blist) SOAP_MESSAGE(fdebug, "Restore previous block sequence\n")); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_save_block(struct soap *soap, char *p, int flag) +{ register size_t n; + register char *q, *s; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Save all blocks in contiguous memory space of %u bytes (%p->%p)\n", (unsigned int)soap->blist->size, soap->blist->ptr, p)); + if (soap->blist->size) + { if (!p) + p = (char*)soap_malloc(soap, soap->blist->size); + if (p) + { for (s = p, q = soap_first_block(soap); q; q = soap_next_block(soap)) + { n = soap_block_size(soap); +#ifndef WITH_NOIDREF + if (flag) + soap_update_ptrs(soap, q, q + n, (long)s - (long)q); /* pointers s and q may or may not be related */ +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy %u bytes from %p to %p\n", (unsigned int)n, q, s)); + memcpy(s, q, n); + s += n; + } + } + else + soap->error = SOAP_EOM; + } + soap_end_block(soap); + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putsize(struct soap *soap, const char *type, int size) +{ return soap_putsizes(soap, type, &size, 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putsizes(struct soap *soap, const char *type, const int *size, int dim) +{ return soap_putsizesoffsets(soap, type, size, NULL, dim); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putsizesoffsets(struct soap *soap, const char *type, const int *size, const int *offset, int dim) +{ int i; + if (!type) + return NULL; + if (soap->version == 2) + { sprintf(soap->type, "%s[%d", type, size[0]); + for (i = 1; i < dim; i++) + sprintf(soap->type + strlen(soap->type), " %d", size[i]); + } + else + { if (offset) + { sprintf(soap->type, "%s[%d", type, size[0] + offset[0]); + for (i = 1; i < dim; i++) + sprintf(soap->type + strlen(soap->type), ",%d", size[i] + offset[i]); + } + else + { sprintf(soap->type, "%s[%d", type, size[0]); + for (i = 1; i < dim; i++) + sprintf(soap->type + strlen(soap->type), ",%d", size[i]); + } + strcat(soap->type, "]"); + } + return soap->type; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putoffset(struct soap *soap, int offset) +{ return soap_putoffsets(soap, &offset, 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putoffsets(struct soap *soap, const int *offset, int dim) +{ register int i; + sprintf(soap->arrayOffset, "[%d", offset[0]); + for (i = 1; i < dim; i++) + sprintf(soap->arrayOffset + strlen(soap->arrayOffset), ",%d", offset[i]); + strcat(soap->arrayOffset, "]"); + return soap->arrayOffset; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_size(const int *size, int dim) +{ register int i, n = size[0]; + for (i = 1; i < dim; i++) + n *= size[i]; + return n; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getoffsets(const char *attr, const int *size, int *offset, int dim) +{ register int i, j = 0; + if (offset) + for (i = 0; i < dim && attr && *attr; i++) + { attr++; + j *= size[i]; + j += offset[i] = (int)atol(attr); + attr = strchr(attr, ','); + } + else + for (i = 0; i < dim && attr && *attr; i++) + { attr++; + j *= size[i]; + j += (int)atol(attr); + attr = strchr(attr, ','); + } + return j; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getsize(const char *attr1, const char *attr2, int *j) +{ register int n, k; + char *s; + *j = 0; + if (!*attr1) + return -1; + if (*attr1 == '[') + attr1++; + n = 1; + for (;;) + { k = (int)soap_strtol(attr1, &s, 10); + n *= k; + if (k < 0 || n > SOAP_MAXARRAYSIZE || s == attr1) + return -1; + attr1 = strchr(s, ','); + if (!attr1) + attr1 = strchr(s, ' '); + if (attr2 && *attr2) + { attr2++; + *j *= k; + k = (int)soap_strtol(attr2, &s, 10); + *j += k; + if (k < 0) + return -1; + attr2 = s; + } + if (!attr1) + break; + attr1++; + } + return n - *j; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getsizes(const char *attr, int *size, int dim) +{ register int i, k, n; + if (!*attr) + return -1; + i = strlen(attr); + n = 1; + do + { for (i = i-1; i >= 0; i--) + if (attr[i] == '[' || attr[i] == ',' || attr[i] == ' ') + break; + k = (int)atol(attr + i + 1); + n *= size[--dim] = k; + if (k < 0 || n > SOAP_MAXARRAYSIZE) + return -1; + } while (i >= 0 && attr[i] != '['); + return n; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getposition(const char *attr, int *pos) +{ register int i, n; + if (!*attr) + return -1; + n = 0; + i = 1; + do + { pos[n++] = (int)atol(attr + i); + while (attr[i] && attr[i] != ',' && attr[i] != ']') + i++; + if (attr[i] == ',') + i++; + } while (n < SOAP_MAXDIMS && attr[i] && attr[i] != ']'); + return n; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_push_namespace(struct soap *soap, const char *id, const char *ns) +{ register struct soap_nlist *np; + register struct Namespace *p; + register short i = -1; + register size_t n, k; + n = strlen(id); + k = strlen(ns) + 1; + p = soap->local_namespaces; + if (p) + { for (i = 0; p->id; p++, i++) + { if (p->ns && !strcmp(ns, p->ns)) + { if (p->out) + { SOAP_FREE(soap, p->out); + p->out = NULL; + } + break; + } + if (p->out) + { if (!strcmp(ns, p->out)) + break; + } + else if (p->in) + { if (!soap_tag_cmp(ns, p->in)) + { if ((p->out = (char*)SOAP_MALLOC(soap, k))) + strcpy(p->out, ns); + break; + } + } + } + if (!p || !p->id) + i = -1; + } + if (i >= 0) + k = 0; + np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k); + if (!np) + return soap->error = SOAP_EOM; + np->next = soap->nlist; + soap->nlist = np; + np->level = soap->level; + np->index = i; + strcpy(np->id, id); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push namespace binding (level=%u) '%s' '%s'\n", soap->level, id, ns)); + if (i < 0) + { np->ns = np->id + n + 1; + strcpy(np->ns, ns); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push NOT OK: no match found for '%s' in namespace mapping table (added to stack anyway)\n", ns)); + } + else + { np->ns = NULL; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push OK ('%s' matches '%s' in namespace table)\n", id, p->id)); + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_pop_namespace(struct soap *soap) +{ register struct soap_nlist *np; + while (soap->nlist && soap->nlist->level >= soap->level) + { np = soap->nlist->next; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Popped namespace binding (level=%u) '%s'\n", soap->level, soap->nlist->id)); + SOAP_FREE(soap, soap->nlist); + soap->nlist = np; + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_match_namespace(struct soap *soap, const char *id1, const char *id2, int n1, int n2) +{ register struct soap_nlist *np = soap->nlist; + while (np && (strncmp(np->id, id1, n1) || np->id[n1])) + np = np->next; + if (np) + { if (np->index < 0 + || (soap->local_namespaces[np->index].id + && (strncmp(soap->local_namespaces[np->index].id, id2, n2) + || soap->local_namespaces[np->index].id[n2]))) + return SOAP_NAMESPACE; + return SOAP_OK; + } + if (n1 == 3 && n1 == n2 && !strcmp(id1, "xml") && !strcmp(id1, id2)) + return SOAP_OK; + return SOAP_SYNTAX_ERROR; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_tag_cmp(const char *s, const char *t) +{ for (;;) + { register int c1 = *s; + register int c2 = *t; + if (!c1 || c1 == '"') + break; + if (c2 != '-') + { if (c1 != c2) + { if (c1 >= 'A' && c1 <= 'Z') + c1 += 'a' - 'A'; + if (c2 >= 'A' && c2 <= 'Z') + c2 += 'a' - 'A'; + } + if (c1 != c2) + { if (c2 != '*') + return 1; + c2 = *++t; + if (!c2) + return 0; + if (c2 >= 'A' && c2 <= 'Z') + c2 += 'a' - 'A'; + for (;;) + { c1 = *s; + if (!c1 || c1 == '"') + break; + if (c1 >= 'A' && c1 <= 'Z') + c1 += 'a' - 'A'; + if (c1 == c2 && !soap_tag_cmp(s + 1, t + 1)) + return 0; + s++; + } + break; + } + } + s++; + t++; + } + if (*t == '*' && !t[1]) + return 0; + return *t; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_match_tag(struct soap *soap, const char *tag1, const char *tag2) +{ register const char *s, *t; + if (!tag1 || !tag2 || !*tag2) + return SOAP_OK; + s = strchr(tag1, ':'); + t = strchr(tag2, ':'); + if (t) + { if (s) + { if (t[1] && SOAP_STRCMP(s + 1, t + 1)) + return SOAP_TAG_MISMATCH; + if (t != tag2 && soap_match_namespace(soap, tag1, tag2, s - tag1, t - tag2)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2)); + return SOAP_TAG_MISMATCH; + } + } + else if (SOAP_STRCMP(tag1, t + 1)) + return SOAP_TAG_MISMATCH; + else if (t != tag2 && soap_match_namespace(soap, tag1, tag2, 0, t - tag2)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2)); + return SOAP_TAG_MISMATCH; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags and (default) namespaces match: '%s' '%s'\n", tag1, tag2)); + return SOAP_OK; + } + if (s) + { if (SOAP_STRCMP(s + 1, tag2)) + return SOAP_TAG_MISMATCH; + } + else if (SOAP_STRCMP(tag1, tag2)) + return SOAP_TAG_MISMATCH; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags match: '%s' '%s'\n", tag1, tag2)); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_match_array(struct soap *soap, const char *type) +{ if (*soap->arrayType) + if (soap_match_tag(soap, soap->arrayType, type) + && soap_match_tag(soap, soap->arrayType, "xsd:anyType") + && soap_match_tag(soap, soap->arrayType, "xsd:ur-type") + ) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array type mismatch: '%s' '%s'\n", soap->arrayType, type)); + return SOAP_TAG_MISMATCH; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ + +#ifdef WITH_OPENSSL +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_rand() +{ unsigned char buf[4]; + ssl_init(); + RAND_pseudo_bytes(buf, 4); + return *(int*)buf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_ssl_server_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *password, const char *cafile, const char *capath, const char *dhfile, const char *randfile, const char *sid) +{ int err; + soap->keyfile = keyfile; + soap->password = password; + soap->cafile = cafile; + soap->capath = capath; + if (dhfile) + { soap->dhfile = dhfile; + soap->rsa = 0; + } + else + { soap->dhfile = NULL; + soap->rsa = 1; + } + soap->randfile = randfile; + soap->require_client_auth = (flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION); + if (!(err = soap->fsslauth(soap))) + if (sid) + SSL_CTX_set_session_id_context(soap->ctx, (unsigned char*)sid, strlen(sid)); + return err; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_ssl_client_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *password, const char *cafile, const char *capath, const char *randfile) +{ soap->keyfile = keyfile; + soap->password = password; + soap->cafile = cafile; + soap->capath = capath; + soap->dhfile = NULL; + soap->rsa = 0; + soap->randfile = randfile; + soap->require_server_auth = (flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION); + return soap->fsslauth(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +static void +ssl_init() +{ static int done = 0; + if (!done) + { done = 1; + SSL_library_init(); +#ifndef WITH_LEAN + SSL_load_error_strings(); +#endif + if (!RAND_load_file("/dev/urandom", 1024)) + { char buf[1024]; + RAND_seed(buf, sizeof(buf)); + while (!RAND_status()) + { int r = rand(); + RAND_seed(&r, sizeof(int)); + } + } + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static const char * +ssl_error(struct soap *soap, int ret) +{ int err = SSL_get_error(soap->ssl, ret); + const char *msg = soap_str_code(h_ssl_error_codes, err); + if (msg) + strcpy(soap->msgbuf, msg); + else + return ERR_error_string(err, soap->msgbuf); + if (ERR_peek_error()) + { unsigned long r; + strcat(soap->msgbuf, "\n"); + while ((r = ERR_get_error())) + ERR_error_string_n(r, soap->msgbuf + strlen(soap->msgbuf), sizeof(soap->msgbuf) - strlen(soap->msgbuf)); + } + else + { switch (ret) + { case 0: + strcpy(soap->msgbuf, "EOF was observed that violates the protocol. The client probably provided invalid authentication information."); + break; + case -1: + sprintf(soap->msgbuf, "Error observed by underlying BIO: %s", strerror(errno)); + break; + } + } + return soap->msgbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +ssl_password(char *buf, int num, int rwflag, void *userdata) +{ if (num < (int)strlen((char*)userdata) + 1) + return 0; + return strlen(strcpy(buf, (char*)userdata)); +} +#endif + +/******************************************************************************/ +/* This callback is included for future references. It should not be deleted +#ifndef PALM_2 +static DH * +ssl_tmp_dh(SSL *ssl, int is_export, int keylength) +{ static DH *dh512 = NULL; + static DH *dh1024 = NULL; + DH *dh; + switch (keylength) + { case 512: + if (!dh512) + { BIO *bio = BIO_new_file("dh512.pem", "r"); + if (bio) + { dh512 = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + return dh512; + } + } + else + return dh512; + default: + if (!dh1024) + { BIO *bio = BIO_new_file("dh1024.pem", "r"); + if (bio) + { dh1024 = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + } + } + dh = dh1024; + } + return dh; +} +#endif +*/ + +/******************************************************************************/ +#ifndef PALM_1 +static int +ssl_auth_init(struct soap *soap) +{ ssl_init(); + if (!soap->ctx) + { if (!(soap->ctx = SSL_CTX_new(SSLv23_method()))) + return soap_set_receiver_error(soap, "SSL error", "Can't setup context", SOAP_SSL_ERROR); + } + if (soap->randfile) + { if (!RAND_load_file(soap->randfile, -1)) + return soap_set_receiver_error(soap, "SSL error", "Can't load randomness", SOAP_SSL_ERROR); + } + if (soap->cafile || soap->capath) + { if (!SSL_CTX_load_verify_locations(soap->ctx, soap->cafile, soap->capath)) + return soap_set_receiver_error(soap, "SSL error", "Can't read CA file and directory", SOAP_SSL_ERROR); + } + if (!SSL_CTX_set_default_verify_paths(soap->ctx)) + return soap_set_receiver_error(soap, "SSL error", "Can't read default CA file and/or directory", SOAP_SSL_ERROR); +/* See below */ + if (soap->keyfile) + { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile)) + return soap_set_receiver_error(soap, "SSL error", "Can't read certificate key file", SOAP_SSL_ERROR); + if (soap->password) + { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password); + SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password); + } + if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM)) + return soap_set_receiver_error(soap, "SSL error", "Can't read key file", SOAP_SSL_ERROR); + } +/* Suggested alternative approach to check cafile first before the key file: + if (soap->password) + { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password); + SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password); + } + if (!soap->cafile || !SSL_CTX_use_certificate_chain_file(soap->ctx, soap->cafile)) + { if (soap->keyfile) + { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile)) + return soap_set_receiver_error(soap, "SSL error", "Can't read certificate or key file", SOAP_SSL_ERROR); + if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM)) + return soap_set_receiver_error(soap, "SSL error", "Can't read key file", SOAP_SSL_ERROR); + } + } +*/ + if (soap->rsa) + { RSA *rsa = RSA_generate_key(512, RSA_F4, NULL, NULL); + if (!SSL_CTX_set_tmp_rsa(soap->ctx, rsa)) + { if (rsa) + RSA_free(rsa); + return soap_set_receiver_error(soap, "SSL error", "Can't set RSA key", SOAP_SSL_ERROR); + } + RSA_free(rsa); + } + else if (soap->dhfile) + { DH *dh = 0; + BIO *bio; + bio = BIO_new_file(soap->dhfile, "r"); + if (!bio) + return soap_set_receiver_error(soap, "SSL error", "Can't read DH file", SOAP_SSL_ERROR); + dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + if (SSL_CTX_set_tmp_dh(soap->ctx, dh) < 0) + { if (dh) + DH_free(dh); + return soap_set_receiver_error(soap, "SSL error", "Can't set DH parameters", SOAP_SSL_ERROR); + } + DH_free(dh); + } + SSL_CTX_set_options(soap->ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2); + SSL_CTX_set_verify(soap->ctx, soap->require_client_auth ? (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT) : soap->require_server_auth ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, soap->fsslverify); +#if (OPENSSL_VERSION_NUMBER < 0x00905100L) + SSL_CTX_set_verify_depth(soap->ctx, 1); +#else + SSL_CTX_set_verify_depth(soap->ctx, 9); +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +ssl_verify_callback(int ok, X509_STORE_CTX *store) +{ +#ifdef SOAP_DEBUG + if (!ok) + { char data[256]; + X509 *cert = X509_STORE_CTX_get_current_cert(store); + fprintf(stderr, "SSL verify error or warning with certificate at depth %d: %s\n", X509_STORE_CTX_get_error_depth(store), X509_verify_cert_error_string(X509_STORE_CTX_get_error(store))); + X509_NAME_oneline(X509_get_issuer_name(cert), data, sizeof(data)); + fprintf(stderr, "certificate issuer %s\n", data); + X509_NAME_oneline(X509_get_subject_name(cert), data, sizeof(data)); + fprintf(stderr, "certificate subject %s\n", data); + } +#endif + /* Note: return 1 to continue, but unsafe progress will be terminated by SSL */ + return ok; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_ssl_accept(struct soap *soap) +{ BIO *bio; + int i, r; + if (!soap_valid_socket(soap->socket)) + return soap_set_receiver_error(soap, "SSL error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR); + if (!soap->ctx && (soap->error = soap->fsslauth(soap))) + return SOAP_INVALID_SOCKET; + if (!soap->ssl) + { soap->ssl = SSL_new(soap->ctx); + if (!soap->ssl) + return soap_set_receiver_error(soap, "SSL error", "SSL_new() failed in soap_ssl_accept()", SOAP_SSL_ERROR); + } + else + SSL_clear(soap->ssl); + soap->imode |= SOAP_ENC_SSL; + soap->omode |= SOAP_ENC_SSL; +#ifdef WIN32 + { u_long nonblocking = 1; + ioctlsocket((SOAP_SOCKET)soap->socket, FIONBIO, &nonblocking); + } +#else + fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL)|O_NONBLOCK); +#endif + bio = BIO_new_socket((SOAP_SOCKET)soap->socket, BIO_NOCLOSE); + SSL_set_bio(soap->ssl, bio, bio); + i = 100; /* 100 * 0.1 ms retries */ + while ((r = SSL_accept(soap->ssl)) <= 0) + { int err = SSL_get_error(soap->ssl, r); + if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) + { struct timeval timeout; + fd_set fd; + if (i-- <= 0) + break; + timeout.tv_sec = 0; + timeout.tv_usec = 100000; + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->socket, &fd); + r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout); + if (r < 0 && soap_socket_errno != SOAP_EINTR) + { soap->errnum = soap_socket_errno; + return SOAP_EOF; + } + } + else + { soap->errnum = err; + break; + } + } +#ifdef WIN32 + { u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)soap->socket, FIONBIO, &blocking); + } +#else + fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL)&~O_NONBLOCK); +#endif + if (r <= 0) + { soap_set_receiver_error(soap, ssl_error(soap, r), "SSL_accept() failed in soap_ssl_accept()", SOAP_SSL_ERROR); + soap_closesock(soap); + return SOAP_SSL_ERROR; + } + if (soap->require_client_auth) + { X509 *peer; + int err; + if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK) + { soap_closesock(soap); + return soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL certificate presented by peer cannot be verified in soap_ssl_accept()", SOAP_SSL_ERROR); + } + peer = SSL_get_peer_certificate(soap->ssl); + if (!peer) + { soap_closesock(soap); + return soap_set_sender_error(soap, "SSL error", "No SSL certificate was presented by the peer in soap_ssl_accept()", SOAP_SSL_ERROR); + } + X509_free(peer); + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#endif /* WITH_OPENSSL */ + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_init(struct soap *soap) +{ soap->errmode = 1; +#ifdef WIN32 + if (tcp_done) + return 0; + else + { WSADATA w; + if (WSAStartup(MAKEWORD(1, 1), &w)) + return -1; + tcp_done = 1; + } +#endif + return 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_done(struct soap *soap) +{ +#ifdef SOAP_DEBUG + int i; +#endif + soap_free(soap); + while (soap->clist) + { struct soap_clist *p = soap->clist->next; + SOAP_FREE(soap, soap->clist); + soap->clist = p; + } + soap->keep_alive = 0; /* to force close the socket */ + soap_closesock(soap); +#ifdef WITH_COOKIES + soap_free_cookies(soap); +#endif + while (soap->plugins) + { register struct soap_plugin *p = soap->plugins->next; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Removing plugin '%s'\n", soap->plugins->id)); + if (soap->plugins->fcopy || !soap->copy) + soap->plugins->fdelete(soap, soap->plugins); + SOAP_FREE(soap, soap->plugins); + soap->plugins = p; + } + soap->fplugin = fplugin; +#ifndef WITH_NOHTTP + soap->fpost = http_post; + soap->fget = http_get; + soap->fform = NULL; + soap->fposthdr = http_post_header; + soap->fresponse = http_response; + soap->fparse = http_parse; + soap->fparsehdr = http_parse_header; +#endif +#ifndef WITH_NOIO +#ifndef WITH_IPV6 + soap->fresolve = tcp_gethost; +#else + soap->fresolve = NULL; +#endif + soap->faccept = tcp_accept; + soap->fopen = tcp_connect; + soap->fclose = tcp_disconnect; + soap->fclosesocket = tcp_closesocket; + soap->fshutdownsocket = tcp_shutdownsocket; + soap->fsend = fsend; + soap->frecv = frecv; + soap->fpoll = soap_poll; +#else + soap->fopen = NULL; + soap->fclose = NULL; + soap->fpoll = NULL; +#endif +#ifndef WITH_LEANER + soap->fprepareinit = NULL; + soap->fpreparesend = NULL; + soap->fpreparerecv = NULL; + soap->fpreparefinal = NULL; +#endif + soap->fseterror = NULL; + soap->fignore = NULL; + soap->fserveloop = NULL; +#ifdef WITH_OPENSSL + if (soap->session) + { SSL_SESSION_free(soap->session); + soap->session = NULL; + } +#endif + if (!soap->copy) + { if (soap_valid_socket(soap->master)) + { soap->fclosesocket(soap, (SOAP_SOCKET)soap->master); + soap->master = SOAP_INVALID_SOCKET; + } +#ifdef WITH_OPENSSL + if (soap->ctx) + { SSL_CTX_free(soap->ctx); + soap->ctx = NULL; + } +#endif + } +#ifdef SOAP_DEBUG + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free logfiles\n")); + for (i = 0; i < SOAP_MAXLOGS; i++) + { if (soap->logfile[i]) + { SOAP_FREE(soap, (void*)soap->logfile[i]); + soap->logfile[i] = NULL; + } + soap_close_logfile(soap, i); + } + soap_free_mht(soap); +#endif +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_cleanup(struct soap *soap) +{ soap_done(soap); +#ifdef WIN32 + if (!tcp_done) + return; + tcp_done = 0; + WSACleanup(); +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static const char* +tcp_error(struct soap *soap) +{ register const char *msg = NULL; + switch (soap->errmode) + { case 0: + msg = soap_strerror(soap); + break; + case 1: + msg = "WSAStartup failed"; + break; + case 2: + { +#ifndef WITH_LEAN + msg = soap_str_code(h_error_codes, soap->errnum); + if (!msg) +#endif + { sprintf(soap->msgbuf, "TCP/UDP IP error %d", soap->errnum); + msg = soap->msgbuf; + } + } + } + return msg; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static const char* +http_error(struct soap *soap, int status) +{ register const char *msg = SOAP_STR_EOS; +#ifndef WITH_LEAN + msg = soap_str_code(h_http_error_codes, status); + if (!msg) + msg = SOAP_STR_EOS; +#endif + return msg; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_IPV6 +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_gethost(struct soap *soap, const char *addr, struct in_addr *inaddr) +{ soap_int32 iadd = -1; + struct hostent hostent, *host = &hostent; +#ifdef VXWORKS + int hostint; + char *addrcopy = (char*)SOAP_MALLOC(soap, strlen(addr) + 1); /*copy of addr. */ + /* inet_addr(), and hostGetByName() expect "char *"; addr is a "const char *". */ + strncpy(addrcopy, addr, strlen(addr)+1); + iadd = inet_addr(addrcopy); +#else +#if defined(_AIXVERSION_431) || defined(TRU64) + struct hostent_data ht_data; +#endif + iadd = inet_addr(addr); +#endif + if (iadd != -1) + { memcpy(inaddr, &iadd, sizeof(iadd)); +#ifdef VXWORKS + SOAP_FREE(soap, addrcopy); +#endif + return SOAP_OK; + } +#if defined(__GLIBC__) + if (gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &host, &soap->errnum) < 0) + host = NULL; +#elif defined(_AIXVERSION_431) || defined(TRU64) + memset((void*)&ht_data, 0, sizeof(ht_data)); + if (gethostbyname_r(addr, &hostent, &ht_data) < 0) + { host = NULL; + soap->errnum = h_errno; + } +#elif defined(HAVE_GETHOSTBYNAME_R) + host = gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &soap->errnum); +#elif defined(VXWORKS) + /* If the DNS resolver library resolvLib has been configured in the vxWorks + * image, a query for the host IP address is sent to the DNS server, if the + * name was not found in the local host table. */ + hostint = hostGetByName(addrcopy); + if (hostint == ERROR) + { host = NULL; + soap->errnum = soap_errno; + } + SOAP_FREE(soap, addrcopy); /*free() is placed after the error checking to assure that + * errno captured is that from hostGetByName() */ +#else + if (!(host = gethostbyname(addr))) + soap->errnum = h_errno; +#endif + if (!host) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Host name not found\n")); + return SOAP_ERR; + } +#ifdef VXWORKS + inaddr->s_addr = hostint; +#else + memcpy(inaddr, host->h_addr, host->h_length); +#endif + return SOAP_OK; +} +#endif +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_connect(struct soap *soap, const char *endpoint, const char *host, int port) +{ +#ifdef WITH_IPV6 + struct addrinfo hints, *res, *ressave; + int err; +#endif + register int fd; +#ifndef WITH_LEAN + int len = SOAP_BUFLEN; + int set = 1; +#endif + if (soap_valid_socket(soap->socket)) + soap->fclosesocket(soap, (SOAP_SOCKET)soap->socket); + soap->socket = SOAP_INVALID_SOCKET; + if (tcp_init(soap)) + { soap->errnum = 0; + soap_set_sender_error(soap, tcp_error(soap), "TCP init failed in tcp_connect()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + soap->errmode = 0; +#ifdef WITH_IPV6 + memset((void*)&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + hints.ai_socktype = SOCK_DGRAM; + else +#endif + hints.ai_socktype = SOCK_STREAM; + soap->errmode = 2; + if (soap->proxy_host) + err = getaddrinfo(soap->proxy_host, soap_int2s(soap, soap->proxy_port), &hints, &res); + else + err = getaddrinfo(host, soap_int2s(soap, port), &hints, &res); + if (err) + { soap_set_sender_error(soap, gai_strerror(err), "getaddrinfo failed in tcp_connect()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + ressave = res; +again: + fd = (int)socket(res->ai_family, res->ai_socktype, res->ai_protocol); + soap->errmode = 0; +#else +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + fd = (int)socket(AF_INET, SOCK_DGRAM, 0); + else +#endif + fd = (int)socket(AF_INET, SOCK_STREAM, 0); +#endif + if (fd < 0) + { soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "socket failed in tcp_connect()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#ifdef SOCKET_CLOSE_ON_EXEC +#ifdef WIN32 +#ifndef UNDER_CE + SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0); +#endif +#else + fcntl(fd, F_SETFD, 1); +#endif +#endif +#ifndef WITH_LEAN + if (soap->connect_flags & SO_LINGER) + { struct linger linger; + memset((void*)&linger, 0, sizeof(linger)); + linger.l_onoff = 1; + linger.l_linger = 0; + if (setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger))) + { soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + } + if ((soap->connect_flags & ~SO_LINGER) && setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, soap->connect_flags & ~SO_LINGER, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "setsockopt failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + if (soap->keep_alive && setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + if (setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + if (setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } +#ifdef TCP_NODELAY + if (!(soap->omode & SOAP_IO_UDP) && setsockopt((SOAP_SOCKET)fd, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } +#endif +#endif + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Opening socket %d to host='%s' port=%d\n", fd, host, port)); +#ifndef WITH_IPV6 + soap->peerlen = sizeof(soap->peer); + memset((void*)&soap->peer, 0, sizeof(soap->peer)); + soap->peer.sin_family = AF_INET; + soap->errmode = 2; + if (soap->proxy_host) + { if (soap->fresolve(soap, soap->proxy_host, &soap->peer.sin_addr)) + { soap_set_sender_error(soap, tcp_error(soap), "get proxy host by name failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + soap->peer.sin_port = htons((short)soap->proxy_port); + } + else + { if (soap->fresolve(soap, host, &soap->peer.sin_addr)) + { soap_set_sender_error(soap, tcp_error(soap), "get host by name failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + soap->peer.sin_port = htons((short)port); + } + soap->errmode = 0; + if ((soap->omode & SOAP_IO_UDP)) + return fd; +#endif +#ifndef WITH_LEAN + if (soap->connect_timeout) +#if defined(WIN32) + { u_long nonblocking = 1; + ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &nonblocking); + } +#elif defined(VXWORKS) + { vx_nonblocking = TRUE; + ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&vx_nonblocking)); /* modified to use fd */ + } +#else + fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)|O_NONBLOCK); +#endif + else +#if defined(WIN32) + { u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &blocking); + } +#elif defined(VXWORKS) + { vx_nonblocking = FALSE; + ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&vx_nonblocking)); /* modified to use fd */ + } +#else + fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)&~O_NONBLOCK); +#endif +#endif + for (;;) + { +#ifdef WITH_IPV6 + if (connect((SOAP_SOCKET)fd, res->ai_addr, res->ai_addrlen)) +#else + if (connect((SOAP_SOCKET)fd, (struct sockaddr*)&soap->peer, sizeof(soap->peer))) +#endif + { +#ifndef WITH_LEAN + if (soap->connect_timeout && (soap_socket_errno == SOAP_EINPROGRESS || soap_socket_errno == SOAP_EWOULDBLOCK)) + { struct timeval timeout; + SOAP_SOCKLEN_T k; + fd_set fds; + if (soap->connect_timeout > 0) + { timeout.tv_sec = soap->connect_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->connect_timeout/1000000; + timeout.tv_usec = -soap->connect_timeout%1000000; + } + FD_ZERO(&fds); + FD_SET((SOAP_SOCKET)fd, &fds); + for (;;) + { int r = select((SOAP_SOCKET)(fd + 1), NULL, &fds, NULL, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n")); + soap_set_sender_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + if (soap_socket_errno != SOAP_EINTR) + { soap->errnum = soap_socket_errno; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); + soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + } + k = (SOAP_SOCKLEN_T)sizeof(soap->errnum); + if (!getsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_ERROR, (char*)&soap->errnum, &k) && !soap->errnum) /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */ + break; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); + soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + else +#endif +#ifdef WITH_IPV6 + if (res->ai_next) + { res = res->ai_next; + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + goto again; + } + else +#endif + if (soap_socket_errno != SOAP_EINTR) + { soap->errnum = soap_socket_errno; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); + soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + } + else + break; + } +#ifdef WITH_IPV6 + soap->peerlen = 0; /* IPv6: already connected so use send() */ + freeaddrinfo(ressave); +#endif +#ifndef WITH_LEAN + if (soap->connect_timeout) +#if defined(WIN32) + { u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &blocking); + } +#elif defined(VXWORKS) + { vx_nonblocking = FALSE; + ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&vx_nonblocking)); /* modified to use fd */ + } +#else + fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)&~O_NONBLOCK); +#endif +#endif + soap->socket = fd; + soap->imode &= ~SOAP_ENC_SSL; + soap->omode &= ~SOAP_ENC_SSL; + if (!strncmp(endpoint, "https:", 6)) + { +#ifdef WITH_OPENSSL + BIO *bio; + int r; + if (soap->proxy_host) + { short v; + unsigned int k = soap->omode; /* make sure we only parse HTTP */ + size_t n = soap->count; /* save the content length */ + soap->omode &= ~SOAP_ENC; /* mask IO and ENC */ + soap->omode |= SOAP_IO_BUFFER; + soap_begin_send(soap); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connecting to proxy server\n")); + sprintf(soap->tmpbuf, "CONNECT %s:%d HTTP/%s", host, port, soap->http_version); + if ((soap->error = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return SOAP_INVALID_SOCKET; +#ifndef WITH_LEAN + if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761) + { sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd); + strcpy(soap->tmpbuf, "Basic "); + soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, strlen(soap->tmpbuf + 262)); + if ((soap->error = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf))) + return soap->error; + } +#endif + if ((soap->error = soap->fposthdr(soap, NULL, NULL)) + || soap_flush(soap)) + return SOAP_INVALID_SOCKET; + soap->omode = k; + k = soap->imode; + soap->imode &= ~SOAP_ENC; /* mask IO and ENC */ + v = soap->version; /* preserve */ + if (soap_begin_recv(soap)) + return SOAP_INVALID_SOCKET; + soap->version = v; /* restore */ + soap->imode = k; /* restore */ + soap->count = n; /* restore */ + soap_begin_send(soap); + } + if (!soap->ctx && (soap->error = soap->fsslauth(soap))) + { soap_set_sender_error(soap, "SSL error", "SSL authentication failed in tcp_connect(): check password, key file, and ca file.", SOAP_SSL_ERROR); + return SOAP_INVALID_SOCKET; + } + soap->ssl = SSL_new(soap->ctx); + if (!soap->ssl) + { soap->error = SOAP_SSL_ERROR; + return SOAP_INVALID_SOCKET; + } + if (soap->session) + { if (!strcmp(soap->session_host, host) && soap->session_port == port) + SSL_set_session(soap->ssl, soap->session); + SSL_SESSION_free(soap->session); + soap->session = NULL; + } + soap->imode |= SOAP_ENC_SSL; + soap->omode |= SOAP_ENC_SSL; + bio = BIO_new_socket((SOAP_SOCKET)fd, BIO_NOCLOSE); + SSL_set_bio(soap->ssl, bio, bio); +#ifndef WITH_LEAN + if (soap->connect_timeout) +#ifdef WIN32 + { u_long nonblocking = 1; + ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &nonblocking); + } +#else + fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)|O_NONBLOCK); +#endif +#endif + for (;;) + { if ((r = SSL_connect(soap->ssl)) <= 0) + { int err = SSL_get_error(soap->ssl, r); + if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) + { soap_set_sender_error(soap, ssl_error(soap, r), "SSL connect failed in tcp_connect()", SOAP_SSL_ERROR); + return SOAP_INVALID_SOCKET; + } + if (soap->connect_timeout) + { struct timeval timeout; + fd_set fds; + if (soap->connect_timeout > 0) + { timeout.tv_sec = soap->connect_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->connect_timeout/1000000; + timeout.tv_usec = -soap->connect_timeout%1000000; + } + FD_ZERO(&fds); + FD_SET((SOAP_SOCKET)soap->socket, &fds); + for (;;) + { int r = select((SOAP_SOCKET)(soap->socket + 1), &fds, NULL, &fds, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n")); + soap_set_sender_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + } + continue; + } + } + break; + } +#ifndef WITH_LEAN + if (soap->connect_timeout) +#ifdef WIN32 + { u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &blocking); + } +#else + fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)&~O_NONBLOCK); +#endif +#endif + if (soap->require_server_auth) + { X509 *peer; + int err; + if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK) + { soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL certificate presented by peer cannot be verified in tcp_connect()", SOAP_SSL_ERROR); + return SOAP_INVALID_SOCKET; + } + peer = SSL_get_peer_certificate(soap->ssl); + if (!peer) + { soap_set_sender_error(soap, "SSL error", "No SSL certificate was presented by the peer in tcp_connect()", SOAP_SSL_ERROR); + return SOAP_INVALID_SOCKET; + } + X509_NAME_get_text_by_NID(X509_get_subject_name(peer), NID_commonName, soap->msgbuf, sizeof(soap->msgbuf)); + X509_free(peer); + if (soap_tag_cmp(soap->msgbuf, host)) + { soap_set_sender_error(soap, "SSL error", "SSL certificate host name mismatch in tcp_connect()", SOAP_SSL_ERROR); + return SOAP_INVALID_SOCKET; + } + } +#else + soap->error = SOAP_SSL_ERROR; + return SOAP_INVALID_SOCKET; +#endif + } + return fd; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_bind(struct soap *soap, const char *host, int port, int backlog) +{ +#ifdef WITH_IPV6 + struct addrinfo *addrinfo; + struct addrinfo hints; + struct addrinfo res; + int err; +#endif +#ifndef WITH_LEAN + int len = SOAP_BUFLEN; + int set = 1; +#endif + if (soap_valid_socket(soap->master)) + { soap->fclosesocket(soap, (SOAP_SOCKET)soap->master); + soap->master = SOAP_INVALID_SOCKET; + } + soap->socket = SOAP_INVALID_SOCKET; + soap->errmode = 1; + if (tcp_init(soap)) + { soap_set_receiver_error(soap, tcp_error(soap), "TCP init failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#ifdef WITH_IPV6 + memset((void*)&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + hints.ai_socktype = SOCK_DGRAM; + else +#endif + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + soap->errmode = 2; + err = getaddrinfo(host, soap_int2s(soap, port), &hints, &addrinfo); + if (addrinfo) + { res = *addrinfo; + soap->peer = *((struct sockaddr_storage*)addrinfo->ai_addr); + soap->peerlen = addrinfo->ai_addrlen; + res.ai_addr = (struct sockaddr*)&soap->peer; + res.ai_addrlen = soap->peerlen; + freeaddrinfo(addrinfo); + } + if (err) + { soap_set_receiver_error(soap, gai_strerror(err), "getaddrinfo failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + soap->master = socket(res.ai_family, res.ai_socktype, res.ai_protocol); +#else +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + soap->master = (int)socket(AF_INET, SOCK_DGRAM, 0); + else +#endif + soap->master = (int)socket(AF_INET, SOCK_STREAM, 0); +#endif + soap->errmode = 0; + if (!soap_valid_socket(soap->master)) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "socket failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + soap->socket = soap->master; +#endif +#ifdef SOCKET_CLOSE_ON_EXEC +#ifdef WIN32 +#ifndef UNDER_CE + SetHandleInformation((HANDLE)soap->master, HANDLE_FLAG_INHERIT, 0); +#endif +#else + fcntl(soap->master, F_SETFD, 1); +#endif +#endif +#ifndef WITH_LEAN + if (soap->bind_flags && setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, soap->bind_flags, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + if (setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + if (setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#ifdef TCP_NODELAY + if (!(soap->omode & SOAP_IO_UDP) && setsockopt((SOAP_SOCKET)soap->master, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#endif +#endif +#ifdef WITH_IPV6 + soap->errmode = 0; + if (bind((SOAP_SOCKET)soap->master, res.ai_addr, res.ai_addrlen)) + { soap->errnum = soap_socket_errno; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n")); + soap_closesock(soap); + soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#else + soap->peerlen = sizeof(soap->peer); + memset((void*)&soap->peer, 0, sizeof(soap->peer)); + soap->peer.sin_family = AF_INET; + soap->errmode = 2; + if (host) + { if (soap->fresolve(soap, host, &soap->peer.sin_addr)) + { soap_set_receiver_error(soap, tcp_error(soap), "get host by name failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + } + else + soap->peer.sin_addr.s_addr = htonl(INADDR_ANY); + soap->peer.sin_port = htons((short)port); + soap->errmode = 0; + if (bind((SOAP_SOCKET)soap->master, (struct sockaddr*)&soap->peer, soap->peerlen)) + { soap->errnum = soap_socket_errno; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n")); + soap_closesock(soap); + soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#endif + if (!(soap->omode & SOAP_IO_UDP) && listen((SOAP_SOCKET)soap->master, backlog)) + { soap->errnum = soap_socket_errno; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n")); + soap_closesock(soap); + soap_set_receiver_error(soap, tcp_error(soap), "listen failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + return soap->master; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_poll(struct soap *soap) +{ +#ifndef WITH_LEAN + struct timeval timeout; + fd_set rfd, sfd, xfd; + int r; + timeout.tv_sec = 0; + timeout.tv_usec = 0; + FD_ZERO(&rfd); + FD_ZERO(&sfd); + FD_ZERO(&xfd); + if (soap_valid_socket(soap->socket)) + { FD_SET((SOAP_SOCKET)soap->socket, &rfd); + FD_SET((SOAP_SOCKET)soap->socket, &sfd); + FD_SET((SOAP_SOCKET)soap->socket, &xfd); + r = select((SOAP_SOCKET)(soap->socket + 1), &rfd, &sfd, &xfd, &timeout); + if (r > 0 && FD_ISSET((SOAP_SOCKET)soap->socket, &xfd)) + r = -1; + } + else if (soap_valid_socket(soap->master)) + { FD_SET((SOAP_SOCKET)soap->master, &sfd); + r = select((SOAP_SOCKET)(soap->master + 1), NULL, &sfd, NULL, &timeout); + } + else + return SOAP_OK; + if (r > 0) + { if (soap_valid_socket(soap->socket) + && FD_ISSET((SOAP_SOCKET)soap->socket, &sfd) + && (!FD_ISSET((SOAP_SOCKET)soap->socket, &rfd) + || recv((SOAP_SOCKET)soap->socket, soap->tmpbuf, 1, MSG_PEEK) > 0)) + return SOAP_OK; + } + else if (r < 0) + { soap->errnum = soap_socket_errno; + if ((soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) && soap_socket_errno != SOAP_EINTR) + { soap_set_receiver_error(soap, tcp_error(soap), "select failed in soap_poll()", SOAP_TCP_ERROR); + return soap->error = SOAP_TCP_ERROR; + } + } + else + soap->errnum = 0; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Polling: other end down on socket=%d select=%d\n", soap->socket, r)); + return SOAP_EOF; +#else + return SOAP_OK; +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_accept(struct soap *soap, int s, struct sockaddr *a, int *n) +{ int fd; + fd = (int)accept((SOAP_SOCKET)s, a, (SOAP_SOCKLEN_T*)n); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */ +#ifdef SOCKET_CLOSE_ON_EXEC +#ifdef WIN32 +#ifndef UNDER_CE + SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0); +#endif +#else + fcntl(fd, F_SETFD, FD_CLOEXEC); +#endif +#endif + return fd; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_accept(struct soap *soap) +{ int n = (int)sizeof(soap->peer); +#ifndef WITH_LEAN + int len = SOAP_BUFLEN; + int set = 1; +#endif + soap->error = SOAP_OK; +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + return soap->socket = soap->master; +#endif + memset((void*)&soap->peer, 0, sizeof(soap->peer)); + soap->socket = SOAP_INVALID_SOCKET; + soap->errmode = 0; + soap->keep_alive = 0; + if (soap_valid_socket(soap->master)) + { for (;;) + { +#ifndef WITH_LEAN + if (soap->accept_timeout) + { struct timeval timeout; + fd_set fd; + if (soap->accept_timeout > 0) + { timeout.tv_sec = soap->accept_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->accept_timeout/1000000; + timeout.tv_usec = -soap->accept_timeout%1000000; + } + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->master, &fd); + for (;;) + { int r = select((SOAP_SOCKET)(soap->master + 1), &fd, &fd, NULL, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + soap_set_receiver_error(soap, "Timeout", "accept failed in soap_accept()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + if (soap_socket_errno != SOAP_EINTR) + { soap->errnum = soap_socket_errno; + soap_closesock(soap); + soap_set_sender_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + } +#if defined(WIN32) + { u_long nonblocking = 1; + ioctlsocket((SOAP_SOCKET)soap->master, FIONBIO, &nonblocking); + } +#elif defined(VXWORKS) + { vx_nonblocking = TRUE; + ioctl((SOAP_SOCKET)soap->master, FIONBIO, (int)(&vx_nonblocking)); + } +#else + fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL)|O_NONBLOCK); +#endif + } + else +#if defined(WIN32) + { u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)soap->master, FIONBIO, &blocking); + } +#elif defined(VXWORKS) + { vx_nonblocking = FALSE; + ioctl((SOAP_SOCKET)soap->master, FIONBIO, (int)(&vx_nonblocking)); + } +#else + fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL)&~O_NONBLOCK); +#endif +#endif + soap->socket = soap->faccept(soap, soap->master, (struct sockaddr*)&soap->peer, &n); + soap->peerlen = (size_t)n; + if (soap_valid_socket(soap->socket)) + { +#ifdef WITH_IPV6 +/* Use soap->host to store the numeric form of the remote host */ + getnameinfo((struct sockaddr*)&soap->peer, n, soap->host, sizeof(soap->host), NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket %d from %s\n", soap->socket, soap->host)); + soap->ip = 0; /* info stored in soap->peer and soap->host */ + soap->port = 0; /* info stored in soap->peer and soap->host */ +#else + soap->ip = ntohl(soap->peer.sin_addr.s_addr); + soap->port = (int)ntohs(soap->peer.sin_port); /* does not return port number on some systems */ + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket %d at port %d from IP %d.%d.%d.%d\n", soap->socket, soap->port, (int)(soap->ip>>24)&0xFF, (int)(soap->ip>>16)&0xFF, (int)(soap->ip>>8)&0xFF, (int)soap->ip&0xFF)); +#endif +#ifndef WITH_LEAN + if (soap->accept_flags & SO_LINGER) + { struct linger linger; + memset((void*)&linger, 0, sizeof(linger)); + linger.l_onoff = 1; + linger.l_linger = 0; + if (setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } + } + if ((soap->accept_flags & ~SO_LINGER) && setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, soap->accept_flags & ~SO_LINGER, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } + if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } + if (setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } + if (setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } +#ifdef TCP_NODELAY + if (!(soap->omode & SOAP_IO_UDP) && setsockopt((SOAP_SOCKET)soap->socket, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } +#endif +#endif + if (soap->accept_timeout) + { +#if defined(WIN32) + u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)soap->master, FIONBIO, &blocking); + ioctlsocket((SOAP_SOCKET)soap->socket, FIONBIO, &blocking); +#elif defined(VXWORKS) + vx_nonblocking = FALSE; + ioctl((SOAP_SOCKET)soap->master, FIONBIO, (int)(&vx_nonblocking)); + ioctl((SOAP_SOCKET)soap->socket, FIONBIO, (int)(&vx_nonblocking)); +#elif defined(PALM) + fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL,0)&~O_NONBLOCK); + fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL,0)&~O_NONBLOCK); +#elif defined(SYMBIAN) + long blocking = 0; + ioctl((SOAP_SOCKET)soap->master, 0/*FIONBIO*/, &blocking); +#else + fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL)&~O_NONBLOCK); + fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL)&~O_NONBLOCK); +#endif + } + soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0); + return soap->socket; + } + if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EAGAIN) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept failed from %s\n", soap->host)); + soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } + } + } + else + { soap->errnum = 0; + soap_set_receiver_error(soap, tcp_error(soap), "no master socket in soap_accept()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_disconnect(struct soap *soap) +{ +#ifdef WITH_OPENSSL + if (soap->ssl) + { int r, s = 0; + if (soap->session) + SSL_SESSION_free(soap->session); + if (*soap->host) + { soap->session = SSL_get1_session(soap->ssl); + if (soap->session) + { strcpy(soap->session_host, soap->host); + soap->session_port = soap->port; + } + } + r = SSL_shutdown(soap->ssl); + if (r != 1) + { s = ERR_get_error(); + if (s) + { if (soap_valid_socket(soap->socket)) + { soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 1); + soap->socket = SOAP_INVALID_SOCKET; + } + r = SSL_shutdown(soap->ssl); + } + } + DBGLOG(TEST, if (s) SOAP_MESSAGE(fdebug, "Shutdown failed: %d\n", SSL_get_error(soap->ssl, r))); + SSL_free(soap->ssl); + soap->ssl = NULL; + if (s) + return SOAP_SSL_ERROR; + ERR_remove_state(0); + } +#endif + if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP)) + { soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 2); + soap->fclosesocket(soap, (SOAP_SOCKET)soap->socket); + soap->socket = SOAP_INVALID_SOCKET; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_closesocket(struct soap *soap, SOAP_SOCKET fd) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Close socket %d\n", (int)fd)); + return closesocket(fd); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_shutdownsocket(struct soap *soap, SOAP_SOCKET fd, int how) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown socket %d how=%d\n", (int)fd, how)); + return shutdown(fd, how); +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_closesock(struct soap *soap) +{ register int status = soap->error; + if (status == SOAP_EOF || status == SOAP_TCP_ERROR || status == SOAP_SSL_ERROR || !soap->keep_alive) + { if (soap->fclose && (soap->error = soap->fclose(soap))) + return soap->error; + soap->keep_alive = 0; + } +#ifdef WITH_ZLIB + if (soap->zlib_state == SOAP_ZLIB_DEFLATE) + deflateEnd(&soap->d_stream); + else if (soap->zlib_state == SOAP_ZLIB_INFLATE) + inflateEnd(&soap->d_stream); + soap->zlib_state = SOAP_ZLIB_NONE; +#endif + return soap->error = status; +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_hash(register const char *s) +{ register size_t h = 0; + while (*s) + h = 65599*h + *s++; + return h % SOAP_IDHASH; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static void +soap_init_pht(struct soap *soap) +{ register int i; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing pointer hashtable\n")); + soap->pblk = NULL; + soap->pidx = 0; + for (i = 0; i < (int)SOAP_PTRHASH; i++) + soap->pht[i] = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_new1(soap_mode mode) +{ return soap_new2(mode, mode); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_new() +{ return soap_new2(SOAP_IO_DEFAULT, SOAP_IO_DEFAULT); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_new2(soap_mode imode, soap_mode omode) +{ struct soap *soap = (struct soap*)malloc(sizeof(struct soap)); + if (soap) + soap_init2(soap, imode, omode); + return soap; +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static void +soap_free_pht(struct soap *soap) +{ register struct soap_pblk *pb, *next; + register int i; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free pointer hashtable\n")); + for (pb = soap->pblk; pb; pb = next) + { next = pb->next; + SOAP_FREE(soap, pb); + } + soap->pblk = NULL; + soap->pidx = 0; + for (i = 0; i < (int)SOAP_PTRHASH; i++) + soap->pht[i] = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_embed(struct soap *soap, const void *p, const struct soap_array *a, int n, const char *tag, int type) +{ register int i; + struct soap_plist *pp; + if (soap->version != 1) + soap->encoding = 1; + if (a) + i = soap_array_pointer_lookup(soap, p, a, n, type, &pp); + else + i = soap_pointer_lookup(soap, p, type, &pp); + if (i) + { if (soap_is_embedded(soap, pp) + || soap_is_single(soap, pp)) + return 0; + soap_set_embedded(soap, pp); + } + return i; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_pointer_lookup(struct soap *soap, const void *p, int type, struct soap_plist **ppp) +{ register struct soap_plist *pp; + *ppp = NULL; + if (p) + { for (pp = soap->pht[soap_hash_ptr(p)]; pp; pp = pp->next) + { if (pp->ptr == p && pp->type == type) + { *ppp = pp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d id=%d\n", p, type, pp->id)); + return pp->id; + } + } + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d: not found\n", p, type)); + return 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_pointer_enter(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp) +{ register int h; + register struct soap_plist *pp; + if (!soap->pblk || soap->pidx >= SOAP_PTRBLK) + { register struct soap_pblk *pb = (struct soap_pblk*)SOAP_MALLOC(soap, sizeof(struct soap_pblk)); + if (!pb) + { soap->error = SOAP_EOM; + return 0; + } + pb->next = soap->pblk; + soap->pblk = pb; + soap->pidx = 0; + } + *ppp = pp = &soap->pblk->plist[soap->pidx++]; + if (a) + h = soap_hash_ptr(a->__ptr); + else + h = soap_hash_ptr(p); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pointer enter location=%p array=%p size=%d dim=%d type=%d id=%d\n", p, a?a->__ptr:NULL, a?a->__size:0, n, type, soap->idnum+1)); + pp->next = soap->pht[h]; + pp->type = type; + pp->mark1 = 0; + pp->mark2 = 0; + pp->ptr = p; + pp->array = a; + soap->pht[h] = pp; + pp->id = ++soap->idnum; + return pp->id; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_array_pointer_lookup(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp) +{ register struct soap_plist *pp; + *ppp = NULL; + if (!p || !a->__ptr) + return 0; + for (pp = soap->pht[soap_hash_ptr(a->__ptr)]; pp; pp = pp->next) + { if (pp->type == type && pp->array && pp->array->__ptr == a->__ptr) + { register int i; + for (i = 0; i < n; i++) + if (((const int*)&pp->array->__size)[i] != ((const int*)&a->__size)[i]) + break; + if (i == n) + { *ppp = pp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d id=%d\n", a->__ptr, type, pp->id)); + return pp->id; + } + } + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d: not found\n", a->__ptr, type)); + return 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_begin_count(struct soap *soap) +{ soap_clr_attr(soap); + soap_set_local_namespaces(soap); +#ifndef WITH_LEANER + if ((soap->mode & SOAP_ENC_DIME) || (soap->omode & SOAP_ENC_DIME)) + soap->mode = soap->omode | SOAP_IO_LENGTH | SOAP_ENC_DIME; + else +#endif + { soap->mode = soap->omode; + if ((soap->mode & SOAP_IO) == SOAP_IO_STORE + || (((soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_ENC_XML)) +#ifndef WITH_LEANER + && !soap->fpreparesend +#endif + )) + soap->mode &= ~SOAP_IO_LENGTH; + else + soap->mode |= SOAP_IO_LENGTH; + } +#ifdef WITH_ZLIB + if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH) + { if (!(soap->mode & SOAP_ENC_DIME)) + soap->mode &= ~SOAP_IO_LENGTH; + if (soap->mode & SOAP_ENC_XML) + soap->mode |= SOAP_IO_BUFFER; + else + soap->mode |= SOAP_IO_STORE; + } +#endif + if (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH)) + soap->mode |= SOAP_XML_TREE; +#ifndef WITH_LEANER + if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME)) + soap->mode |= SOAP_ENC_MIME; + else + soap->mode &= ~SOAP_ENC_MTOM; + if (soap->mode & SOAP_ENC_MIME) + soap_select_mime_boundary(soap); + soap->dime.list = soap->dime.last; /* keep track of last DIME attachment */ +#endif + soap->count = 0; + soap->ns = 0; + soap->null = 0; + soap->position = 0; + soap->mustUnderstand = 0; + soap->encoding = 0; + soap->part = SOAP_BEGIN; + soap->idnum = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin count phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count)); +#ifndef WITH_LEANER + soap->dime.count = 0; /* count # of attachments */ + soap->dime.size = 0; /* accumulate total size of attachments */ + if (soap->fprepareinit && (soap->mode & SOAP_IO) != SOAP_IO_STORE) + return soap->error = soap->fprepareinit(soap); +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_end_count(struct soap *soap) +{ +#ifndef WITH_LEANER + if (soap->fpreparefinal) + return soap->error = soap->fpreparefinal(soap); +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of count phase\n")); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_begin_send(struct soap *soap) +{ soap->error = SOAP_OK; + soap_clr_attr(soap); + soap_set_local_namespaces(soap); + soap->mode = soap->omode | (soap->mode & (SOAP_IO_LENGTH | SOAP_ENC_DIME)); +#ifdef WITH_ZLIB + if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH) + { if (soap->mode & SOAP_ENC_XML) + soap->mode |= SOAP_IO_BUFFER; + else + soap->mode |= SOAP_IO_STORE; + } +#endif +#ifdef WITH_UDP + if ((soap->mode & SOAP_IO_UDP)) + { soap->mode |= SOAP_ENC_XML; + if (soap->count > SOAP_BUFLEN) + return soap->error = SOAP_UDP_ERROR; + } +#endif + if ((soap->mode & SOAP_IO) == SOAP_IO_FLUSH && soap_valid_socket(soap->socket)) + { if (soap->count || (soap->mode & SOAP_IO_LENGTH) || (soap->mode & SOAP_ENC_XML)) + soap->mode |= SOAP_IO_BUFFER; + else + soap->mode |= SOAP_IO_STORE; + } + soap->mode &= ~SOAP_IO_LENGTH; + if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) + soap_new_block(soap); + if (!(soap->mode & SOAP_IO_KEEPALIVE)) + soap->keep_alive = 0; + if (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH)) + soap->mode |= SOAP_XML_TREE; +#ifndef WITH_LEANER + if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME)) + { soap->mode |= SOAP_ENC_MIME; + soap->mode &= ~SOAP_ENC_DIME; + } + else + soap->mode &= ~SOAP_ENC_MTOM; + if (soap->mode & SOAP_ENC_MIME) + soap_select_mime_boundary(soap); +#ifdef WIN32 +#ifndef UNDER_CE +#ifndef WITH_FASTCGI + if (!soap_valid_socket(soap->socket)) /* Set win32 stdout or soap->sendfd to BINARY, e.g. to support DIME */ +#ifdef __BORLANDC__ + setmode((SOAP_SOCKET)soap->sendfd, O_BINARY); +#else + _setmode((SOAP_SOCKET)soap->sendfd, _O_BINARY); +#endif +#endif +#endif +#endif +#endif + if (soap->mode & SOAP_IO) + { soap->bufidx = 0; + soap->buflen = 0; + } + soap->chunksize = 0; + soap->ns = 0; + soap->null = 0; + soap->position = 0; + soap->mustUnderstand = 0; + soap->encoding = 0; + soap->idnum = 0; + soap->level = 0; +#ifdef WITH_ZLIB + soap->z_ratio_out = 1.0; + if ((soap->mode & SOAP_ENC_ZLIB) && soap->zlib_state != SOAP_ZLIB_DEFLATE) + { +#ifdef WITH_GZIP + memcpy(soap->z_buf, "\37\213\10\0\0\0\0\0\0\377", 10); + soap->d_stream.next_out = (Byte*)soap->z_buf + 10; + soap->d_stream.avail_out = SOAP_BUFLEN - 10; + soap->z_crc = crc32(0L, NULL, 0); + if (deflateInit2(&soap->d_stream, soap->z_level, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY) != Z_OK) +#else + soap->d_stream.next_out = (Byte*)soap->z_buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + if (deflateInit(&soap->d_stream, soap->z_level) != Z_OK) +#endif + return soap->error = SOAP_ZLIB_ERROR; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflate initialized\n")); + soap->zlib_state = SOAP_ZLIB_DEFLATE; + } +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin send phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count)); + soap->part = SOAP_BEGIN; +#ifndef WITH_LEANER + if (soap->fprepareinit && (soap->mode & SOAP_IO) == SOAP_IO_STORE) + soap->fprepareinit(soap); +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_embedded(struct soap *soap, const void *p, int t) +{ struct soap_plist *pp; + if (soap_pointer_lookup(soap, p, t, &pp)) + { pp->mark1 = 1; + pp->mark2 = 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded %p type=%d mark set to 1\n", p, t)); + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_reference(struct soap *soap, const void *p, int t) +{ struct soap_plist *pp; + if (!p || (soap->mode & SOAP_XML_TREE)) + return 1; + if (soap_pointer_lookup(soap, p, t, &pp)) + { if (pp->mark1 == 0) + { pp->mark1 = 2; + pp->mark2 = 2; + } + } + else if (soap_pointer_enter(soap, p, NULL, 0, t, &pp)) + { pp->mark1 = 0; + pp->mark2 = 0; + } + else + return 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reference %p type=%d (%d %d)\n", p, t, (int)pp->mark1, (int)pp->mark2)); + return pp->mark1; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_array_reference(struct soap *soap, const void *p, const struct soap_array *a, int n, int t) +{ register int i; + struct soap_plist *pp; + if (!p || !a->__ptr) + return 1; + i = soap_array_pointer_lookup(soap, p, a, n, t, &pp); + if (i) + { if (pp->mark1 == 0) + { pp->mark1 = 2; + pp->mark2 = 2; + } + } + else if (!soap_pointer_enter(soap, p, a, n, t, &pp)) + return 1; + else + { pp->mark1 = 0; + pp->mark2 = 0; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array reference %p ptr=%p dim=%d type=%d (%d %d)\n", p, a->__ptr, n, t, (int)pp->mark1, (int)pp->mark2)); + return pp->mark1; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_embedded_id(struct soap *soap, int id, const void *p, int t) +{ struct soap_plist *pp; + if (soap->mode & SOAP_XML_TREE) + return id; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id %p type=%d id=%d\n", p, t, id)); + if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER) + { if (id < 0) + { id = soap_pointer_lookup(soap, p, t, &pp); + if (id) + { if (soap->mode & SOAP_IO_LENGTH) + pp->mark1 = 2; + else + pp->mark2 = 2; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id multiref id=%d %p type=%d = (%d %d)\n", id, p, t, (int)pp->mark1, (int)pp->mark2)); + } + return -1; + } + return id; + } + if (id < 0) + id = soap_pointer_lookup(soap, p, t, &pp); + else if (id && !soap_pointer_lookup(soap, p, t, &pp)) + return 0; + if (id && pp) + { if (soap->mode & SOAP_IO_LENGTH) + pp->mark1 = 1; + else + pp->mark2 = 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id embedded ref id=%d %p type=%d = (%d %d)\n", id, p, t, (int)pp->mark1, (int)pp->mark2)); + } + return id; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_is_embedded(struct soap *soap, struct soap_plist *pp) +{ if (!pp) + return 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Is embedded? %d %d\n", (int)pp->mark1, (int)pp->mark2)); + if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER) + { if (soap->mode & SOAP_IO_LENGTH) + return pp->mark1 != 0; + return pp->mark2 != 0; + } + if (soap->mode & SOAP_IO_LENGTH) + return pp->mark1 == 1; + return pp->mark2 == 1; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_is_single(struct soap *soap, struct soap_plist *pp) +{ if (soap->part == SOAP_IN_HEADER) + return 1; + if (!pp) + return 0; + if (soap->mode & SOAP_IO_LENGTH) + return pp->mark1 == 0; + return pp->mark2 == 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_embedded(struct soap *soap, struct soap_plist *pp) +{ if (!pp) + return; + if (soap->mode & SOAP_IO_LENGTH) + pp->mark1 = 1; + else + pp->mark2 = 1; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_attachment(struct soap *soap, const char *tag, int id, const void *p, const struct soap_array *a, const char *aid, const char *atype, const char *aoptions, int n, const char *type, int t) +{ struct soap_plist *pp; + int i; + if (!p || !a->__ptr || (!aid && !atype)) + return soap_element_id(soap, tag, id, p, a, n, type, t); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attachment tag='%s' id='%s' (%d) type='%s'\n", tag, aid?aid:"", id, atype?atype:"")); + i = soap_array_pointer_lookup(soap, p, a, n, t, &pp); + if (!i) + { i = soap_pointer_enter(soap, p, a, n, t, &pp); + if (!i) + { soap->error = SOAP_EOM; + return -1; + } + } + if (id < 0) + id = i; + if (!aid) + { sprintf(soap->tmpbuf, soap->dime_id_format, id); + aid = soap_strdup(soap, soap->tmpbuf); + } + /* Add MTOM xop:Include element when necessary */ + /* TODO: this code to be obsoleted with new import/xop.h conventions */ + if ((soap->mode & SOAP_ENC_MTOM) && strcmp(tag, "xop:Include")) + { if (soap_element_begin_out(soap, tag, 0, type) + || soap_element_href(soap, "xop:Include", 0, "href", aid) + || soap_element_end_out(soap, tag)) + return soap->error; + } + else if (soap_element_href(soap, tag, 0, "href", aid)) + return soap->error; + if (soap->mode & SOAP_IO_LENGTH) + { if (pp->mark1 != 3) + { struct soap_multipart *content; + if (soap->mode & SOAP_ENC_MTOM) + content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, (char*)a->__ptr, a->__size); + else + content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, (char*)a->__ptr, a->__size); + if (!content) + { soap->error = SOAP_EOM; + return -1; + } + if (!strncmp(aid, "cid:", 4)) /* RFC 2111 */ + { if (soap->mode & SOAP_ENC_MTOM) + { char *s = (char*)soap_malloc(soap, strlen(aid) - 1); + if (s) + { *s = '<'; + strcpy(s + 1, aid + 4); + strcat(s, ">"); + content->id = s; + } + } + else + content->id = aid + 4; + } + else + content->id = aid; + content->type = atype; + content->options = aoptions; + content->encoding = SOAP_MIME_BINARY; + pp->mark1 = 3; + } + } + else + pp->mark2 = 3; + return -1; +} +#endif +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static void +soap_init_iht(struct soap *soap) +{ register int i; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing ID hashtable\n")); + for (i = 0; i < SOAP_IDHASH; i++) + soap->iht[i] = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static void +soap_free_iht(struct soap *soap) +{ register int i; + register struct soap_ilist *ip, *p; + register struct soap_flist *fp, *fq; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free ID hashtable\n")); + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = p) + { for (fp = ip->flist; fp; fp = fq) + { fq = fp->next; + SOAP_FREE(soap, fp); + } + p = ip->next; + SOAP_FREE(soap, ip); + } + soap->iht[i] = NULL; + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +struct soap_ilist * +SOAP_FMAC2 +soap_lookup(struct soap *soap, const char *id) +{ register struct soap_ilist *ip; + for (ip = soap->iht[soap_hash(id)]; ip; ip = ip->next) + if (!strcmp(ip->id, id)) + return ip; + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +struct soap_ilist * +SOAP_FMAC2 +soap_enter(struct soap *soap, const char *id) +{ register size_t h; + register struct soap_ilist *ip; + ip = (struct soap_ilist*)SOAP_MALLOC(soap, sizeof(struct soap_ilist) + strlen(id)); + if (ip) + { h = soap_hash(id); + strcpy(ip->id, id); + ip->next = soap->iht[h]; + soap->iht[h] = ip; + return ip; + } + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_malloc(struct soap *soap, size_t n) +{ register char *p; + if (!n) + return (void*)SOAP_NON_NULL; + if (!soap) + return SOAP_MALLOC(soap, n); + n += (-(long)n) & 7; + if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(void*) + sizeof(size_t)))) + { soap->error = SOAP_EOM; + return NULL; + } + /* keep chain of alloced cells for later destruction */ + soap->alloced = 1; + *(void**)(p + n) = soap->alist; + *(size_t*)(p + n + sizeof(void*)) = n; + soap->alist = p + n; + return p; +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +static void +soap_init_mht(struct soap *soap) +{ register int i; + for (i = 0; i < (int)SOAP_PTRHASH; i++) + soap->mht[i] = NULL; +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +static void +soap_free_mht(struct soap *soap) +{ register int i; + register struct soap_mlist *mp, *mq; + for (i = 0; i < (int)SOAP_PTRHASH; i++) + { for (mp = soap->mht[i]; mp; mp = mq) + { mq = mp->next; + if (mp->live) + fprintf(stderr, "%s(%d): malloc() = %p not freed (memory leak or forgot to call soap_end()?)\n", mp->file, mp->line, mp->ptr); + free(mp); + } + soap->mht[i] = NULL; + } +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_track_malloc(struct soap *soap, const char *file, int line, size_t size) +{ register void *p = malloc(size); + if (soap) + { register int h = soap_hash_ptr(p); + register struct soap_mlist *mp = (struct soap_mlist*)malloc(sizeof(struct soap_mlist)); + if (soap->fdebug[SOAP_INDEX_TEST]) + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): malloc(%lu) = %p\n", file, line, (unsigned long)size, p)); + mp->next = soap->mht[h]; + mp->ptr = p; + mp->file = file; + mp->line = line; + mp->live = 1; + soap->mht[h] = mp; + } + return p; +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_track_free(struct soap *soap, const char *file, int line, void *p) +{ register int h = soap_hash_ptr(p); + register struct soap_mlist *mp; + for (mp = soap->mht[h]; mp; mp = mp->next) + if (mp->ptr == p) + break; + if (mp) + { if (mp->live) + { free(p); + if (soap->fdebug[SOAP_INDEX_TEST]) + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): free(%p)\n", file, line, p)); + mp->live = 0; + } + else + fprintf(stderr, "%s(%d): free(%p) double free of pointer malloced at %s(%d)\n", file, line, p, mp->file, mp->line); + } + else + fprintf(stderr, "%s(%d): free(%p) pointer not malloced\n", file, line, p); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +static void +soap_track_unlink(struct soap *soap, const void *p) +{ register int h = soap_hash_ptr(p); + register struct soap_mlist *mp; + for (mp = soap->mht[h]; mp; mp = mp->next) + if (mp->ptr == p) + break; + if (mp) + mp->live = 0; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_dealloc(struct soap *soap, void *p) +{ if (!soap) + return; + if (p) + { register char **q; + for (q = (char**)&soap->alist; *q; q = *(char***)q) + { if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*)))) + { *q = **(char***)q; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Freed data at %p\n", p)); + SOAP_FREE(soap, p); + return; + } + } + soap_delete(soap, p); + } + else + { register char *q; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free all soap_malloc() data\n")); + while (soap->alist) + { q = (char*)soap->alist; + soap->alist = *(void**)q; + q -= *(size_t*)(q + sizeof(void*)); + SOAP_FREE(soap, q); + } + } + /* we must assume these were deallocated: */ + soap->action = NULL; + soap->fault = NULL; + soap->header = NULL; + soap->userid = NULL; + soap->passwd = NULL; + soap->authrealm = NULL; +#ifndef WITH_LEANER + soap_clr_mime(soap); +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_delete(struct soap *soap, void *p) +{ register struct soap_clist **cp = &soap->clist; + if (p) + { while (*cp) + { if (p == (*cp)->ptr) + { register struct soap_clist *q = *cp; + *cp = q->next; + q->fdelete(q); + SOAP_FREE(soap, q); + return; + } + cp = &(*cp)->next; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: address not in list\n", p)); + } + else + { while (*cp) + { register struct soap_clist *q = *cp; + *cp = q->next; + if (q->ptr == (void*)soap->fault) + soap->fault = NULL; /* this was deallocated */ + else if (q->ptr == (void*)soap->header) + soap->header = NULL; /* this was deallocated */ + q->fdelete(q); + SOAP_FREE(soap, q); + } + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +struct soap_clist * +SOAP_FMAC2 +soap_link(struct soap *soap, void *p, int t, int n, void (*fdelete)(struct soap_clist*)) +{ register struct soap_clist *cp; + if ((cp = (struct soap_clist*)SOAP_MALLOC(soap, sizeof(struct soap_clist)))) + { cp->next = soap->clist; + cp->type = t; + cp->size = n; + cp->ptr = p; + cp->fdelete = fdelete; + soap->clist = cp; + } + return cp; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_unlink(struct soap *soap, const void *p) +{ register char **q; + register struct soap_clist **cp; + if (!soap || !p) + return; + for (q = (char**)&soap->alist; *q; q = *(char***)q) + { if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*)))) + { *q = **(char***)q; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked data %p\n", p)); +#ifdef SOAP_DEBUG + soap_track_unlink(soap, p); +#endif + return; + } + } + for (cp = &soap->clist; *cp; cp = &(*cp)->next) + { if (p == (*cp)->ptr) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked class instance %p\n", p)); + q = (char**)*cp; + *cp = (*cp)->next; + SOAP_FREE(soap, q); + return; + } + } +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_lookup_type(struct soap *soap, const char *id) +{ register struct soap_ilist *ip; + if (id && *id) + { ip = soap_lookup(soap, id); + if (ip) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup id='%s' type=%d\n", id, ip->type)); + return ip->type; + } + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "lookup type id='%s' NOT FOUND! Need to get it from xsi:type\n", id)); + return 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_id_lookup(struct soap *soap, const char *id, void **p, int t, size_t n, unsigned int k) +{ struct soap_ilist *ip; + void **q; + if (!p || !id || !*id) + return p; + ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */ + if (!ip) + { ip = soap_enter(soap, id); /* new hash table entry for string id */ + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding first href='%s' type=%d %p (%u bytes)\n", id, t, p, (unsigned int)n)); + ip->type = t; + ip->size = n; + ip->link = p; + ip->copy = NULL; + ip->flist = NULL; + ip->ptr = NULL; + ip->level = k; + *p = NULL; + } + else if (ip->ptr) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolved href='%s' type=%d location=%p (%u bytes)\n", id, t, ip->ptr, (unsigned int)n)); + if (ip->type != t) + { strcpy(soap->id, id); + soap->error = SOAP_HREF; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility: id type=%d href type=%d\n", ip->type, t)); + return NULL; + } + while (ip->level < k) + { q = (void**)soap_malloc(soap, sizeof(void*)); + if (!q) + return NULL; + *p = (void*)q; + p = q; + k--; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); + } + *p = ip->ptr; + } + else if (ip->level > k) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving level %u pointers to href='%s'\n", ip->level, id)); + while (ip->level > k) + { void *s, **r = &ip->link; + q = (void**)ip->link; + while (q) + { *r = (void*)soap_malloc(soap, sizeof(void*)); + s = *q; + *q = *r; + r = (void**)*r; + q = (void**)s; + } + *r = NULL; + ip->size = n; + ip->copy = NULL; + ip->level = ip->level - 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); + } + q = (void**)ip->link; + ip->link = p; + *p = (void*)q; + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarded href='%s' type=%d location=%p (%u bytes)\n", id, t, p, (unsigned int)n)); + while (ip->level < k) + { q = (void**)soap_malloc(soap, sizeof(void*)); + *p = q; + p = q; + k--; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); + } + q = (void**)ip->link; + ip->link = p; + *p = (void*)q; + } + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_id_forward(struct soap *soap, const char *href, void *p, int st, int tt, size_t n, unsigned int k, void (*fcopy)(struct soap*, int, int, void*, const void*, size_t)) +{ struct soap_ilist *ip; + if (!p || !href || !*href) + return p; + ip = soap_lookup(soap, href); /* lookup pointer to hash table entry for string id */ + if (!ip) + { ip = soap_enter(soap, href); /* new hash table entry for string id */ + ip->type = st; + ip->size = n; + ip->link = NULL; + ip->copy = NULL; + ip->ptr = NULL; + ip->level = 0; + ip->flist = NULL; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "New entry href='%s' type=%d size=%lu level=%d location=%p\n", href, st, (unsigned long)n, k, p)); + } + else if (ip->type != st || (ip->level == k && ip->size != n)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n", href, ip->type, (unsigned long)ip->size, k, st, (unsigned long)n)); + strcpy(soap->id, href); + soap->error = SOAP_HREF; + return NULL; + } + if (fcopy || n < sizeof(void*) || *href != '#') + { register struct soap_flist *fp = (struct soap_flist*)SOAP_MALLOC(soap, sizeof(struct soap_flist)); + if (!fp) + { soap->error = SOAP_EOM; + return NULL; + } + fp->next = ip->flist; + fp->type = tt; + fp->ptr = p; + fp->level = k; + if (fcopy) + fp->fcopy = fcopy; + else + fp->fcopy = soap_fcopy; + ip->flist = fp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding type=%d (target type=%d) size=%lu location=%p level=%u href='%s'\n", st, tt, (unsigned long)n, p, k, href)); + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding copying address %p for type=%d href='%s'\n", p, st, href)); + *(void**)p = ip->copy; + ip->copy = p; + } + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_id_enter(struct soap *soap, const char *id, void *p, int t, size_t n, unsigned int k, const char *type, const char *arrayType, void *(*finstantiate)(struct soap*, int, const char*, const char*, size_t*)) +{ +#ifndef WITH_NOIDREF + struct soap_ilist *ip; +#endif + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Enter id='%s' type=%d loc=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k)); + soap->alloced = 0; + if (!p) + { if (finstantiate) + p = finstantiate(soap, t, type, arrayType, &n); + else + p = soap_malloc(soap, n); + if (p) + soap->alloced = 1; + } +#ifndef WITH_NOIDREF + if (!id || !*id) +#endif + return p; +#ifndef WITH_NOIDREF + ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */ + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Lookup entry id='%s for location=%p'\n", id, p)); + if (!ip) + { ip = soap_enter(soap, id); /* new hash table entry for string id */ + ip->type = t; + ip->link = NULL; + ip->copy = NULL; + ip->flist = NULL; + ip->size = n; + ip->ptr = p; + ip->level = k; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "New entry id='%s' type=%d size=%lu level=%u location=%p\n", id, t, (unsigned long)n, k, p)); + } + else if ((ip->type != t || (ip->level == k && ip->size != n)) && (ip->copy || ip->flist)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n", id, ip->type, (unsigned long)ip->size, k, t, (unsigned long)n)); + strcpy(soap->id, id); + soap->error = SOAP_HREF; + return NULL; + } + else if (ip->ptr) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Multiply defined id='%s'\n", id)); + strcpy(soap->id, id); + soap->error = SOAP_DUPLICATE_ID; + return NULL; + } + else + { ip->size = n; + ip->ptr = p; + ip->level = k; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update entry id='%s' type=%d location=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k)); + } + return ip->ptr; +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_fcopy(struct soap *soap, int st, int tt, void *p, const void *q, size_t n) +{ DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Copying data type=%d (target type=%d) %p -> %p (%lu bytes)\n", st, tt, q, p, (unsigned long)n)); + memcpy(p, q, n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_end_send(struct soap *soap) +{ +#ifndef WITH_LEANER + if (soap->dime.list) + { /* SOAP body referenced attachments must appear first */ + soap->dime.last->next = soap->dime.first; + soap->dime.first = soap->dime.list->next; + soap->dime.list->next = NULL; + soap->dime.last = soap->dime.list; + } + if (soap_putdime(soap) || soap_putmime(soap)) + return soap->error; + soap->mime.list = NULL; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->dime.list = NULL; + soap->dime.first = NULL; + soap->dime.last = NULL; +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End send\n")); + if (soap->mode & SOAP_IO) /* need to flush the remaining data in buffer */ + { if (soap_flush(soap)) +#ifdef WITH_ZLIB + { if (soap->mode & SOAP_ENC_ZLIB && soap->zlib_state == SOAP_ZLIB_DEFLATE) + { soap->zlib_state = SOAP_ZLIB_NONE; + deflateEnd(&soap->d_stream); + } + return soap->error; + } +#else + return soap->error; +#endif +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { int r; + soap->d_stream.avail_in = 0; + do + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating remainder\n")); + r = deflate(&soap->d_stream, Z_FINISH); + if (soap->d_stream.avail_out != SOAP_BUFLEN) + { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN - soap->d_stream.avail_out)) + { soap->zlib_state = SOAP_ZLIB_NONE; + deflateEnd(&soap->d_stream); + return soap->error; + } + soap->d_stream.next_out = (Byte*)soap->z_buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + } + } while (r == Z_OK); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out)); + soap->z_ratio_out = (float)soap->d_stream.total_out / (float)soap->d_stream.total_in; + soap->mode &= ~SOAP_ENC_ZLIB; + soap->zlib_state = SOAP_ZLIB_NONE; + if (deflateEnd(&soap->d_stream) != Z_OK || r != Z_STREAM_END) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to end deflate: %s\n", soap->d_stream.msg?soap->d_stream.msg:"")); + return soap->error = SOAP_ZLIB_ERROR; + } +#ifdef WITH_GZIP + soap->z_buf[0] = soap->z_crc & 0xFF; + soap->z_buf[1] = (soap->z_crc >> 8) & 0xFF; + soap->z_buf[2] = (soap->z_crc >> 16) & 0xFF; + soap->z_buf[3] = (soap->z_crc >> 24) & 0xFF; + soap->z_buf[4] = soap->d_stream.total_in & 0xFF; + soap->z_buf[5] = (soap->d_stream.total_in >> 8) & 0xFF; + soap->z_buf[6] = (soap->d_stream.total_in >> 16) & 0xFF; + soap->z_buf[7] = (soap->d_stream.total_in >> 24) & 0xFF; + if (soap_flush_raw(soap, soap->z_buf, 8)) + return soap->error; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip crc32=%lu\n", (unsigned long)soap->z_crc)); +#endif + } +#endif + if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) + { char *p; +#ifndef WITH_NOHTTP + if (!(soap->mode & SOAP_ENC_XML)) + { soap->mode--; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending buffered message of length %u\n", (unsigned int)soap->blist->size)); + if (soap->status >= SOAP_POST) + soap->error = soap->fpost(soap, soap->endpoint, soap->host, soap->port, soap->path, soap->action, soap->blist->size); + else if (soap->status != SOAP_STOP) + soap->error = soap->fresponse(soap, soap->status, soap->blist->size); + if (soap->error || soap_flush(soap)) + return soap->error; + soap->mode++; + } +#endif + for (p = soap_first_block(soap); p; p = soap_next_block(soap)) + { DBGMSG(SENT, p, soap_block_size(soap)); + if ((soap->error = soap->fsend(soap, p, soap_block_size(soap)))) + { soap_end_block(soap); + return soap->error; + } + } + soap_end_block(soap); + } +#ifndef WITH_LEANER + else if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) + { DBGMSG(SENT, "\r\n0\r\n\r\n", 7); + if ((soap->error = soap->fsend(soap, "\r\n0\r\n\r\n", 7))) + return soap->error; + } +#endif + } +#ifdef WITH_OPENSSL + if (!soap->ssl && soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP)) + soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 1); /* Send TCP FIN */ +#else + if (soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP)) + soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 1); /* Send TCP FIN */ +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of send phase\n")); + soap->omode &= ~SOAP_XML_SEC; + soap->count = 0; + soap->part = SOAP_END; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_end_recv(struct soap *soap) +{ soap->part = SOAP_END; +#ifndef WITH_LEANER + if ((soap->mode & SOAP_ENC_DIME) && soap_getdime(soap)) + return soap->error; + soap->dime.list = soap->dime.first; + soap->dime.first = NULL; + soap->dime.last = NULL; + if ((soap->mode & SOAP_ENC_MIME) && soap_getmime(soap)) + return soap->error; + soap->mime.list = soap->mime.first; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = NULL; +#endif + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "End of receive message ok\n")); +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { soap->mode &= ~SOAP_ENC_ZLIB; + memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN); + soap->bufidx = (char*)soap->d_stream.next_in - soap->z_buf; + soap->buflen = soap->z_buflen; + soap->zlib_state = SOAP_ZLIB_NONE; + if (inflateEnd(&soap->d_stream) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; +#ifdef WITH_GZIP + if (soap->zlib_in == SOAP_ZLIB_GZIP) + { soap_wchar c; + short i; + for (i = 0; i < 8; i++) + { if ((int)(c = soap_getchar(soap)) == EOF) + return soap->error = SOAP_EOF; + soap->z_buf[i] = (char)c; + } + if (soap->z_crc != ((uLong)(unsigned char)soap->z_buf[0] | ((uLong)(unsigned char)soap->z_buf[1] << 8) | ((uLong)(unsigned char)soap->z_buf[2] << 16) | ((uLong)(unsigned char)soap->z_buf[3] << 24))) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: crc check failed, message corrupted? (crc32=%lu)\n", (unsigned long)soap->z_crc)); + return soap->error = SOAP_ZLIB_ERROR; + } + if (soap->d_stream.total_out != ((uLong)(unsigned char)soap->z_buf[4] | ((uLong)(unsigned char)soap->z_buf[5] << 8) | ((uLong)(unsigned char)soap->z_buf[6] << 16) | ((uLong)(unsigned char)soap->z_buf[7] << 24))) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: incorrect message length\n")); + return soap->error = SOAP_ZLIB_ERROR; + } + } +#endif + } +#endif + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) + while ((int)soap_getchar(soap) != EOF) /* advance to last chunk */ + ; + if (soap->fdisconnect && (soap->error = soap->fdisconnect(soap))) + return soap->error; +#ifndef WITH_NOIDREF + return soap_resolve(soap); +#else +#ifndef WITH_LEANER + if (soap->xlist) + { if (soap->mode & SOAP_ENC_MTOM) + return soap->error = SOAP_MIME_HREF; + return soap->error = SOAP_DIME_HREF; + } +#endif + return SOAP_OK; +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_free(struct soap *soap) +{ register struct Namespace *ns; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free namespace stack\n")); + while (soap->nlist) + { register struct soap_nlist *np = soap->nlist->next; + SOAP_FREE(soap, soap->nlist); + soap->nlist = np; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free any remaining temp blocks\n")); + while (soap->blist) + soap_end_block(soap); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute storage\n")); + while (soap->attributes) + { register struct soap_attribute *tp = soap->attributes->next; + if (soap->attributes->value) + SOAP_FREE(soap, soap->attributes->value); + SOAP_FREE(soap, soap->attributes); + soap->attributes = tp; + } +#ifdef WITH_FAST + if (soap->labbuf) + SOAP_FREE(soap, soap->labbuf); + soap->labbuf = NULL; + soap->lablen = 0; + soap->labidx = 0; +#endif + ns = soap->local_namespaces; + if (ns) + { for (; ns->id; ns++) + { if (ns->out) + { if (soap->encodingStyle == ns->out) + soap->encodingStyle = SOAP_STR_EOS; + SOAP_FREE(soap, ns->out); + ns->out = NULL; + } + if (soap->encodingStyle == ns->ns) + soap->encodingStyle = SOAP_STR_EOS; + } + SOAP_FREE(soap, soap->local_namespaces); + soap->local_namespaces = NULL; + } +#ifndef WITH_LEANER + while (soap->xlist) + { struct soap_xlist *xp = soap->xlist->next; + SOAP_FREE(soap, soap->xlist); + soap->xlist = xp; + } +#endif +#ifndef WITH_NOIDREF + soap_free_pht(soap); + soap_free_iht(soap); +#endif +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +static void +soap_init_logs(struct soap *soap) +{ int i; + for (i = 0; i < SOAP_MAXLOGS; i++) + { soap->logfile[i] = NULL; + soap->fdebug[i] = NULL; + } +} +#endif + +/******************************************************************************/ +#if !defined(WITH_LEAN) || defined(SOAP_DEBUG) +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_open_logfile(struct soap *soap, int i) +{ if (soap->logfile[i]) + soap->fdebug[i] = fopen(soap->logfile[i], i < 2 ? "ab" : "a"); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +static void +soap_close_logfile(struct soap *soap, int i) +{ if (soap->fdebug[i]) + { fclose(soap->fdebug[i]); + soap->fdebug[i] = NULL; + } +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_close_logfiles(struct soap *soap) +{ int i; + for (i = 0; i < SOAP_MAXLOGS; i++) + soap_close_logfile(soap, i); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +static void +soap_set_logfile(struct soap *soap, int i, const char *logfile) +{ char *s = NULL; + soap_close_logfile(soap, i); + if (soap->logfile[i]) + SOAP_FREE(soap, (void*)soap->logfile[i]); + if (logfile) + if ((s = (char*)SOAP_MALLOC(soap, strlen(logfile) + 1))) + strcpy(s, logfile); + soap->logfile[i] = s; +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_recv_logfile(struct soap *soap, const char *logfile) +{ soap_set_logfile(soap, SOAP_INDEX_RECV, logfile); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_sent_logfile(struct soap *soap, const char *logfile) +{ soap_set_logfile(soap, SOAP_INDEX_SENT, logfile); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_test_logfile(struct soap *soap, const char *logfile) +{ soap_set_logfile(soap, SOAP_INDEX_TEST, logfile); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_copy(struct soap *soap) +{ return soap_copy_context((struct soap*)malloc(sizeof(struct soap)), soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_copy_context(struct soap *copy, struct soap *soap) +{ if (copy) + { register struct soap_plugin *p; + memcpy(copy, soap, sizeof(struct soap)); + copy->copy = 1; + copy->user = NULL; + copy->error = SOAP_OK; + copy->userid = NULL; + copy->passwd = NULL; + copy->nlist = NULL; + copy->blist = NULL; + copy->clist = NULL; + copy->alist = NULL; + copy->attributes = NULL; +#ifdef WITH_FAST + copy->labbuf = NULL; + copy->lablen = 0; + copy->labidx = 0; +#endif +#ifdef SOAP_DEBUG + soap_init_mht(copy); +#endif + copy->local_namespaces = NULL; +#ifndef WITH_NOIDREF + soap_init_iht(copy); + soap_init_pht(copy); +#endif + copy->header = NULL; + copy->fault = NULL; + copy->action = NULL; + *copy->host = '\0'; +#ifndef WITH_LEAN +#ifdef WITH_COOKIES + copy->cookies = soap_copy_cookies(copy); +#else + copy->cookies = NULL; +#endif +#endif +#ifdef SOAP_DEBUG + soap_init_logs(copy); + soap_set_recv_logfile(copy, soap->logfile[SOAP_INDEX_RECV]); + soap_set_sent_logfile(copy, soap->logfile[SOAP_INDEX_SENT]); + soap_set_test_logfile(copy, soap->logfile[SOAP_INDEX_TEST]); +#endif + copy->plugins = NULL; + for (p = soap->plugins; p; p = p->next) + { register struct soap_plugin *q = (struct soap_plugin*)SOAP_MALLOC(copy, sizeof(struct soap_plugin)); + if (!q) + return NULL; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying plugin '%s'\n", p->id)); + *q = *p; + if (p->fcopy && (soap->error = p->fcopy(copy, q, p))) + { SOAP_FREE(copy, q); + return NULL; + } + q->next = copy->plugins; + copy->plugins = q; + } + } + else + soap->error = SOAP_EOM; + return copy; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_init(struct soap *soap) +{ soap->version = 0; + soap_imode(soap, SOAP_IO_DEFAULT); + soap_omode(soap, SOAP_IO_DEFAULT); + soap->copy = 0; + soap->plugins = NULL; + soap->user = NULL; + soap->userid = NULL; + soap->passwd = NULL; +#ifndef WITH_NOHTTP + soap->fpost = http_post; + soap->fget = http_get; + soap->fform = NULL; + soap->fposthdr = http_post_header; + soap->fresponse = http_response; + soap->fparse = http_parse; + soap->fparsehdr = http_parse_header; +#endif + soap->fconnect = NULL; + soap->fdisconnect = NULL; +#ifndef WITH_NOIO +#ifndef WITH_IPV6 + soap->fresolve = tcp_gethost; +#else + soap->fresolve = NULL; +#endif + soap->faccept = tcp_accept; + soap->fopen = tcp_connect; + soap->fclose = tcp_disconnect; + soap->fclosesocket = tcp_closesocket; + soap->fshutdownsocket = tcp_shutdownsocket; + soap->fsend = fsend; + soap->frecv = frecv; + soap->fpoll = soap_poll; +#else + soap->fopen = NULL; + soap->fclose = NULL; + soap->fpoll = NULL; +#endif +#ifndef WITH_LEANER + soap->fprepareinit = NULL; + soap->fpreparesend = NULL; + soap->fpreparerecv = NULL; + soap->fpreparefinal = NULL; +#endif + soap->fseterror = NULL; + soap->fignore = NULL; + soap->fserveloop = NULL; + soap->fplugin = fplugin; +#ifndef WITH_LEANER + soap->fdimereadopen = NULL; + soap->fdimewriteopen = NULL; + soap->fdimereadclose = NULL; + soap->fdimewriteclose = NULL; + soap->fdimeread = NULL; + soap->fdimewrite = NULL; +#endif + soap->float_format = "%.8g"; /* .8 preserves single FP precision as much as possible, but might not be very efficient */ + soap->double_format = "%.17lg"; /* .17 preserves double FP precision as much as possible, but might not be very efficient */ + soap->dime_id_format = "cid:id%d"; /* default DIME id format */ + soap->http_version = "1.1"; + soap->actor = NULL; + soap->max_keep_alive = SOAP_MAXKEEPALIVE; + soap->keep_alive = 0; + soap->recv_timeout = 0; + soap->send_timeout = 0; + soap->connect_timeout = 0; + soap->accept_timeout = 0; + soap->socket_flags = 0; + soap->connect_flags = 0; + soap->bind_flags = 0; + soap->accept_flags = 0; + soap->ip = 0; +#ifdef WITH_FAST + soap->labbuf = NULL; + soap->lablen = 0; + soap->labidx = 0; +#endif + soap->encodingStyle = SOAP_STR_EOS; +#ifndef WITH_NONAMESPACES + soap->namespaces = namespaces; +#else + soap->namespaces = NULL; +#endif + soap->local_namespaces = NULL; + soap->nlist = NULL; + soap->blist = NULL; + soap->clist = NULL; + soap->alist = NULL; + soap->attributes = NULL; + soap->header = NULL; + soap->fault = NULL; + soap->master = SOAP_INVALID_SOCKET; + soap->socket = SOAP_INVALID_SOCKET; + soap->os = NULL; + soap->is = NULL; +#ifndef WITH_LEANER + soap->dom = NULL; + soap->dime.list = NULL; + soap->dime.first = NULL; + soap->dime.last = NULL; + soap->mime.list = NULL; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = NULL; + soap->mime.start = NULL; + soap->xlist = NULL; +#endif +#ifndef UNDER_CE + soap->recvfd = 0; + soap->sendfd = 1; +#else + soap->recvfd = stdin; + soap->sendfd = stdout; +#endif + soap->host[0] = '\0'; + soap->port = 0; + soap->action = NULL; + soap->proxy_host = NULL; + soap->proxy_port = 8080; + soap->proxy_userid = NULL; + soap->proxy_passwd = NULL; + soap->authrealm = NULL; + soap->prolog = NULL; +#ifdef WITH_OPENSSL + soap->fsslauth = ssl_auth_init; + soap->fsslverify = ssl_verify_callback; + soap->bio = NULL; + soap->ssl = NULL; + soap->ctx = NULL; + soap->require_server_auth = 0; + soap->require_client_auth = 0; + soap->rsa = 0; + soap->keyfile = NULL; + soap->password = NULL; + soap->dhfile = NULL; + soap->cafile = NULL; + soap->capath = NULL; + soap->crlfile = NULL; + soap->randfile = NULL; + soap->session = NULL; +#endif +#ifdef WITH_ZLIB + soap->zlib_state = SOAP_ZLIB_NONE; + soap->zlib_in = SOAP_ZLIB_NONE; + soap->zlib_out = SOAP_ZLIB_NONE; + soap->d_stream.zalloc = NULL; + soap->d_stream.zfree = NULL; + soap->d_stream.opaque = NULL; + soap->z_level = 6; +#endif +#ifndef WITH_LEAN + soap->c14ninclude = NULL; + soap->c14nexclude = NULL; + soap->cookies = NULL; + soap->cookie_domain = NULL; + soap->cookie_path = NULL; + soap->cookie_max = 32; +#endif +#ifdef SOAP_DEBUG + soap_init_mht(soap); + soap_init_logs(soap); + soap_set_recv_logfile(soap, "RECV.log"); + soap_set_sent_logfile(soap, "SENT.log"); + soap_set_test_logfile(soap, NULL); +#endif +#ifdef WMW_RPM_IO + soap->rpmreqid = NULL; +#endif /* WMW_RPM_IO */ +#ifdef PALM + palmNetLibOpen(); +#endif +#ifndef WITH_NOIDREF + soap_init_iht(soap); + soap_init_pht(soap); +#endif + soap_begin(soap); +#ifdef SOAP_DEBUG + soap_set_test_logfile(soap, "TEST.log"); +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_init1(struct soap *soap, soap_mode mode) +{ soap_init2(soap, mode, mode); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_init2(struct soap *soap, soap_mode imode, soap_mode omode) +{ soap_init(soap); + soap_imode(soap, imode); + soap_omode(soap, omode); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_begin(struct soap *soap) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing\n")); + if (!soap->keep_alive) + { soap->buflen = 0; + soap->bufidx = 0; + } + soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0); + soap->null = 0; + soap->position = 0; + soap->encoding = 0; + soap->mustUnderstand = 0; + soap->mode = 0; + soap->ns = 0; + soap->part = SOAP_END; + soap->alloced = 0; + soap->count = 0; + soap->length = 0; + soap->cdata = 0; + soap->error = SOAP_OK; + soap->peeked = 0; + soap->ahead = 0; + soap->idnum = 0; + soap->level = 0; + soap->endpoint[0] = '\0'; +#ifndef WITH_LEANER + soap->dime.chunksize = 0; + soap->dime.buflen = 0; +#endif + soap_free(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_end(struct soap *soap) +{ register struct soap_clist *cp; + soap_free(soap); + soap_dealloc(soap, NULL); + while (soap->clist) + { cp = soap->clist->next; + SOAP_FREE(soap, soap->clist); + soap->clist = cp; + } + soap_closesock(soap); +#ifdef SOAP_DEBUG + soap_close_logfiles(soap); +#endif +#ifdef PALM + palmNetLibClose(); +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_namespaces(struct soap *soap, struct Namespace *p) +{ register struct Namespace *ns = soap->local_namespaces; + register struct soap_nlist *np, *nq, *nr; + register unsigned int level = soap->level; + soap->namespaces = p; + soap->local_namespaces = NULL; + soap_set_local_namespaces(soap); + /* reverse the namespace list */ + np = soap->nlist; + soap->nlist = NULL; + if (np) + { nq = np->next; + np->next = NULL; + while (nq) + { nr = nq->next; + nq->next = np; + np = nq; + nq = nr; + } + } + /* then push on new stack */ + while (np) + { register const char *s; + soap->level = np->level; /* preserve element nesting level */ + s = np->ns; + if (!s && np->index >= 0 && ns) + { s = ns[np->index].out; + if (!s) + s = ns[np->index].ns; + } + if (s && soap_push_namespace(soap, np->id, s)) + return soap->error; + nq = np; + np = np->next; + SOAP_FREE(soap, nq); + } + if (ns) + { register int i; + for (i = 0; ns[i].id; i++) + { if (ns[i].out) + { SOAP_FREE(soap, ns[i].out); + ns[i].out = NULL; + } + } + SOAP_FREE(soap, ns); + } + soap->level = level; /* restore level */ + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_local_namespaces(struct soap *soap) +{ if (soap->namespaces && !soap->local_namespaces) + { register const struct Namespace *ns1; + register struct Namespace *ns2; + register size_t n = 1; + for (ns1 = soap->namespaces; ns1->id; ns1++) + n++; + n *= sizeof(struct Namespace); + ns2 = (struct Namespace*)SOAP_MALLOC(soap, n); + if (ns2) + { memcpy(ns2, soap->namespaces, n); + if (ns2[0].ns) + { if (!strcmp(ns2[0].ns, soap_env1)) + soap->version = 1; + else + soap->version = 2; + } + soap->local_namespaces = ns2; + } + } +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +#ifndef PALM_1 +SOAP_FMAC1 +const char * +SOAP_FMAC2 +soap_strsearch(const char *big, const char *little) +{ size_t n = strlen(little); + const char *s = big; + while (s) + { if (!strncmp(s, little, n) && (s[n] == '\0' || s[n] == ' ')) + return s; + s = strchr(s, ' '); + if (s) + s++; + } + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static struct soap_nlist * +soap_lookup_ns(struct soap *soap, const char *tag, size_t n) +{ register struct soap_nlist *np; + for (np = soap->nlist; np; np = np->next) + { if (!strncmp(np->id, tag, n) && !np->id[n]) + return np; + } + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static struct soap_nlist * +soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized) +{ register struct soap_nlist *np; + size_t n, k; + if (soap_strsearch(soap->c14nexclude, id)) + return NULL; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push namespace binding (level=%u) '%s' '%s'\n", soap->level, id, ns?ns:"")); + if (!utilized) + { for (np = soap->nlist; np; np = np->next) + { if (!strcmp(np->id, id) && (!np->ns || !strcmp(np->ns, ns))) + break; + } + if (np) + { if (np->index == 1) + utilized = np->index; + else + return NULL; + } + } + n = strlen(id); + if (ns) + k = strlen(ns); + else + k = 0; + np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k + 1); + if (!np) + { soap->error = SOAP_EOM; + return NULL; + } + np->next = soap->nlist; + soap->nlist = np; + strcpy(np->id, id); + if (ns) + { np->ns = np->id + n + 1; + strcpy(np->ns, ns); + } + else + np->ns = NULL; + np->level = soap->level; + np->index = utilized; + return np; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static void +soap_utilize_ns(struct soap *soap, const char *tag, size_t n) +{ register struct soap_nlist *np = soap_lookup_ns(soap, tag, n); + if (np) + { if (np->index == 0) + soap_push_ns(soap, np->id, np->ns, 1); + } + else + { strncpy(soap->tmpbuf, tag, n); + soap->tmpbuf[n] = '\0'; + soap_push_ns(soap, soap->tmpbuf, NULL, 1); + } +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static void +soap_pop_ns(struct soap *soap) +{ soap_pop_namespace(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element(struct soap *soap, const char *tag, int id, const char *type) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element begin tag='%s' id='%d' type='%s'\n", tag, id, type?type:"")); +#ifdef WITH_DOM + if (soap->mode & SOAP_XML_DOM) + { register struct soap_dom_element *elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element)); + if (!elt) + return soap->error = SOAP_EOM; + elt->soap = soap; + elt->next = NULL; + elt->prnt = soap->dom; + elt->name = soap_strdup(soap, tag); + elt->elts = NULL; + elt->atts = NULL; + elt->nstr = NULL; + elt->data = NULL; + elt->wide = NULL; + elt->node = NULL; + elt->type = 0; + elt->head = NULL; + elt->tail = NULL; + if (soap->dom) + { struct soap_dom_element *p = soap->dom->elts; + if (p) + { while (p->next) + p = p->next; + p->next = elt; + } + else + soap->dom->elts = elt; + } + soap->dom = elt; + } + else + { +#endif + soap->level++; +#ifndef WITH_LEAN + if (!soap->ns) + { if (!(soap->mode & SOAP_XML_CANONICAL) + && soap_send(soap, soap->prolog ? soap->prolog : "\n")) + return soap->error; + } + else if (soap->mode & SOAP_XML_INDENT) + { if (soap->ns == 1 && soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1)) + return soap->error; + soap->body = 1; + } +#endif + if (soap_send_raw(soap, "<", 1) + || soap_send(soap, tag)) + return soap->error; +#ifdef WITH_DOM + } +#endif + if (!soap->ns) + { struct Namespace *ns; + for (ns = soap->local_namespaces; ns && ns->id; ns++) + { if (*ns->id && (ns->out || ns->ns)) + { sprintf(soap->tmpbuf, "xmlns:%s", ns->id); + if (soap_attribute(soap, soap->tmpbuf, ns->out ? ns->out : ns->ns)) + return soap->error; + } + } + } + soap->ns = 1; /* start with 0 or 2, but should be one to continue */ +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { const char *s = strchr(tag, ':'); + if (s) + soap_utilize_ns(soap, tag, s - tag); + } +#endif + if (id > 0) + { sprintf(soap->tmpbuf, "_%d", id); + if (soap_attribute(soap, "id", soap->tmpbuf)) + return soap->error; + } + if (type && *type) + { if (soap_attribute(soap, "xsi:type", type)) + return soap->error; +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { const char *s = strchr(type, ':'); + if (s) + soap_utilize_ns(soap, type, s - type); + } +#endif + } + if (soap->null && soap->position > 0) + { int i; + sprintf(soap->tmpbuf, "[%d", soap->positions[0]); + for (i = 1; i < soap->position; i++) + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), ",%d", soap->positions[i]); + strcat(soap->tmpbuf, "]"); + if (soap_attribute(soap, "SOAP-ENC:position", soap->tmpbuf)) + return soap->error; + } + if (soap->mustUnderstand) + { if (soap->actor && *soap->actor) + { if (soap_attribute(soap, soap->version == 2 ? "SOAP-ENV:role" : "SOAP-ENV:actor", soap->actor)) + return soap->error; + } + if (soap_attribute(soap, "SOAP-ENV:mustUnderstand", soap->version == 2 ? "true" : "1")) + return soap->error; + soap->mustUnderstand = 0; + } + if (soap->encoding) + { if (soap->encodingStyle && soap->local_namespaces) + { if (!*soap->encodingStyle) + { if (soap->local_namespaces[1].out) + soap->encodingStyle = soap->local_namespaces[1].out; + else + soap->encodingStyle = soap->local_namespaces[1].ns; + } + if (soap_attribute(soap, "SOAP-ENV:encodingStyle", soap->encodingStyle)) + return soap->error; + } + soap->encoding = 0; + } + soap->null = 0; + soap->position = 0; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_begin_out(struct soap *soap, const char *tag, int id, const char *type) +{ if (*tag == '-') + return SOAP_OK; + if (soap_element(soap, tag, id, type)) + return soap->error; + return soap_element_start_end_out(soap, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +#ifndef HAVE_STRRCHR +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_strrchr(const char *s, int t) +{ register char *r = NULL; + while (*s) + if (*s++ == t) + r = (char*)s - 1; + return r; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +#ifndef HAVE_STRTOL +SOAP_FMAC1 +long +SOAP_FMAC2 +soap_strtol(const char *s, char **t, int b) +{ register long n = 0; + register int c; + while (*s > 0 && *s <= 32) + s++; + if (b == 10) + { short neg = 0; + if (*s == '-') + { s++; + neg = 1; + } + else if (*s == '+') + s++; + while ((c = *s) && c >= '0' && c <= '9') + { if (n >= 214748364 && (n > 214748364 || c >= '8')) + break; + n *= 10; + n += c - '0'; + s++; + } + if (neg) + n = -n; + } + else /* b == 16 and value is always positive */ + { while ((c = *s)) + { if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'F') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'f') + c -= 'a' - 10; + if (n > 0x07FFFFFF) + break; + n <<= 4; + n += c; + s++; + } + } + if (t) + *t = (char*)s; + return n; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +#ifndef HAVE_STRTOUL +SOAP_FMAC1 +unsigned long +SOAP_FMAC2 +soap_strtoul(const char *s, char **t, int b) +{ unsigned long n = 0; + register int c; + while (*s > 0 && *s <= 32) + s++; + if (b == 10) + { if (*s == '+') + s++; + while ((c = *s) && c >= '0' && c <= '9') + { if (n >= 429496729 && (n > 429496729 || c >= '6')) + break; + n *= 10; + n += c - '0'; + s++; + } + } + else /* b == 16 */ + { while ((c = *s)) + { if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'F') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'f') + c -= 'a' - 10; + if (n > 0x0FFFFFFF) + break; + n <<= 4; + n += c; + s++; + } + } + if (t) + *t = (char*)s; + return n; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_array_begin_out(struct soap *soap, const char *tag, int id, const char *type, const char *offset) +{ if (soap_element(soap, tag, id, "SOAP-ENC:Array")) + return soap->error; + if (soap->version == 2) + { const char *s; + s = soap_strrchr(type, '['); + if ((size_t)(s - type) < sizeof(soap->tmpbuf)) + { strncpy(soap->tmpbuf, type, s - type); + soap->tmpbuf[s - type] = '\0'; + if (type && *type && (soap_attribute(soap, "SOAP-ENC:itemType", soap->tmpbuf))) + return soap->error; + if (s && (soap_attribute(soap, "SOAP-ENC:arraySize", s + 1))) + return soap->error; + } + } + else + { if (offset && (soap_attribute(soap, "SOAP-ENC:offset", offset))) + return soap->error; + if (type && *type && (soap_attribute(soap, "SOAP-ENC:arrayType", type))) + return soap->error; + } +#ifndef WITH_LEAN + if (type && *type && (soap->mode & SOAP_XML_CANONICAL)) + { const char *s = strchr(type, ':'); + if (s) + soap_utilize_ns(soap, type, s - type); + } +#endif + return soap_element_start_end_out(soap, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_start_end_out(struct soap *soap, const char *tag) +{ register struct soap_attribute *tp; +#ifdef WITH_DOM + register struct soap_dom_attribute **att; + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { att = &soap->dom->atts; + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible) + { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); + if (!*att) + return soap->error = SOAP_EOM; + (*att)->next = NULL; + (*att)->nstr = NULL; + (*att)->name = soap_strdup(soap, tp->name); + (*att)->data = soap_strdup(soap, tp->value); + (*att)->wide = NULL; + (*att)->soap = soap; + tp->visible = 0; + } + } + return SOAP_OK; + } +#endif +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { struct soap_nlist *np; + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible && tp->name) + { const char *s = strchr(tp->name, ':'); + if (s) + soap_utilize_ns(soap, tp->name, s - tp->name); + } + } + for (np = soap->nlist; np; np = np->next) + { if (np->index == 1 && np->ns) + { sprintf(soap->tmpbuf, "xmlns:%s", np->id); + soap_set_attr(soap, soap->tmpbuf, np->ns); + np->index = 2; + } + } + } +#endif + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible) + { if (soap_send(soap, " ") || soap_send(soap, tp->name)) + return soap->error; + if (tp->visible == 2 && tp->value) + if (soap_send_raw(soap, "=\"", 2) + || soap_string_out(soap, tp->value, 1) + || soap_send_raw(soap, "\"", 1)) + return soap->error; + tp->visible = 0; + } + } + if (tag) + { +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { if (soap_send_raw(soap, ">", 1) + || soap_element_end_out(soap, tag)) + return soap->error; + } + else +#endif + soap->level--; /* decrement level just before /> */ + if (soap_send_raw(soap, "/>", 2)) + return soap->error; + return SOAP_OK; + } + return soap_send_raw(soap, ">", 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_end_out(struct soap *soap, const char *tag) +{ if (*tag == '-') + return SOAP_OK; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element ending tag='%s'\n", tag)); +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { if (soap->dom->prnt) + soap->dom = soap->dom->prnt; + return SOAP_OK; + } +#endif +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + soap_pop_ns(soap); + if (soap->mode & SOAP_XML_INDENT) + { if (!soap->body) + { if (soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1)) + return soap->error; + } + soap->body = 0; + } +#endif + if (soap_send_raw(soap, "error; + soap->level--; /* decrement level just before > */ + return soap_send_raw(soap, ">", 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_ref(struct soap *soap, const char *tag, int id, int href) +{ register int n = 0; + if (soap->version == 2) + n = 1; + sprintf(soap->href, "#_%d", href); + return soap_element_href(soap, tag, id, "href" + n, soap->href + n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_href(struct soap *soap, const char *tag, int id, const char *ref, const char *val) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element '%s' reference %s='%s'\n", tag, ref, val)); + if (soap_element(soap, tag, id, NULL) + || soap_attribute(soap, ref, val) + || soap_element_start_end_out(soap, tag)) + return soap->error; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_null(struct soap *soap, const char *tag, int id, const char *type) +{ struct soap_attribute *tp; + for (tp = soap->attributes; tp; tp = tp->next) + if (tp->visible) + break; + if (tp || (soap->version == 2 && soap->position > 0) || id > 0 || (soap->mode & SOAP_XML_NIL)) + { if (soap_element(soap, tag, id, type)) + return soap->error; + if (soap->part != SOAP_IN_HEADER && soap->encodingStyle) + if (soap_attribute(soap, "xsi:nil", "true")) + return soap->error; + return soap_element_start_end_out(soap, tag); + } + soap->null = 1; + soap->position = 0; + soap->mustUnderstand = 0; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_id(struct soap *soap, const char *tag, int id, const void *p, const struct soap_array *a, int n, const char *type, int t) +{ if (!p || (a && !a->__ptr)) + { soap_element_null(soap, tag, id, type); + return -1; + } +#ifndef WITH_NOIDREF + if (soap->mode & SOAP_XML_TREE) + return 0; + if (id < 0) + { struct soap_plist *pp; + if (a) + id = soap_array_pointer_lookup(soap, p, a, n, t, &pp); + else + id = soap_pointer_lookup(soap, p, t, &pp); + if (id) + { if (soap_is_embedded(soap, pp)) + { soap_element_ref(soap, tag, 0, id); + return -1; + } + if (soap_is_single(soap, pp)) + return 0; + soap_set_embedded(soap, pp); + } + } + return id; +#else + return 0; +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_result(struct soap *soap, const char *tag) +{ if (soap->version == 2 && soap->encodingStyle) + if (soap_element(soap, "SOAP-RPC:result", 0, NULL) + || soap_attribute(soap, "xmlns:SOAP-RPC", soap_rpc) + || soap_element_start_end_out(soap, NULL) + || soap_string_out(soap, tag, 0) + || soap_element_end_out(soap, "SOAP-RPC:result")) + return soap->error; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_attribute(struct soap *soap, const char *name, const char *value) +{ +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { register struct soap_dom_attribute *a = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); + a->next = soap->dom->atts; + a->nstr = NULL; + a->name = soap_strdup(soap, name); + a->data = soap_strdup(soap, value); + a->wide = NULL; + a->soap = soap; + soap->dom->atts = a; + return SOAP_OK; + } +#endif +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { /* TODO: consider using this code to handle default namespace + if (!strncmp(name, "xmlns", 5) && (name[5] == ':' || name[5] == '\0')) + { if (name[5] == ':') + soap_push_ns(soap, name + 6, value, 0); + else + soap_push_ns(soap, "", value, 0); + } + */ + if (!strncmp(name, "xmlns:", 6)) + soap_push_ns(soap, name + 6, value, 0); + else if (soap_set_attr(soap, name, value)) + return soap->error; + } + else +#endif + { if (soap_send(soap, " ") || soap_send(soap, name)) + return soap->error; + if (value) + if (soap_send_raw(soap, "=\"", 2) + || soap_string_out(soap, value, 1) + || soap_send_raw(soap, "\"", 1)) + return soap->error; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_begin_in(struct soap *soap, const char *tag, int nillable) +{ if (!soap_peek_element(soap)) + { if (soap->other) + return soap->error = SOAP_TAG_MISMATCH; + if (tag && *tag == '-') + return SOAP_OK; + if (!(soap->error = soap_match_tag(soap, soap->tag, tag))) + { soap->peeked = 0; + if (soap->body) + soap->level++; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:"" )); + if (!nillable && soap->null && (soap->mode & SOAP_XML_STRICT)) + return soap->error = SOAP_NULL; + } + } + else if (soap->error == SOAP_NO_TAG && tag && *tag == '-') + soap->error = SOAP_OK; + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_end_in(struct soap *soap, const char *tag) +{ register soap_wchar c; + register char *s; + register const char *t; + register int n = 0; + if (tag && *tag == '-') + return SOAP_OK; + soap->level--; + soap_pop_namespace(soap); +#ifdef WITH_DOM + /* this whitespace or mixed content is not insignificant for DOM */ + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { if (!soap->peeked && !soap_string_in(soap, 3, -1, -1)) + return soap->error; + if (soap->dom->prnt) + soap->dom = soap->dom->prnt; + } +#endif + if (soap->peeked) + { if (soap->error == SOAP_NO_TAG) + soap->error = SOAP_OK; + if (*soap->tag) + n++; + soap->peeked = 0; + } + do + { while (((c = soap_get(soap)) != SOAP_TT)) + { if ((int)c == EOF) + return soap->error = SOAP_EOF; + if (c == SOAP_LT) + n++; + else if (c == '/') + { c = soap_get(soap); + if (c == SOAP_GT) + n--; + else + soap_unget(soap, c); + } + } + } while (n--); + s = soap->tag; + while (soap_notblank(c = soap_getutf8(soap))) + *s++ = (char)c; + *s = '\0'; + if ((int)c == EOF) + return soap->error = SOAP_EOF; + while (soap_blank(c)) + c = soap_get(soap); + if (c != SOAP_GT) + return soap->error = SOAP_SYNTAX_ERROR; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:"")); + if (!tag || !*tag) + return SOAP_OK; + if ((s = strchr(soap->tag, ':'))) + s++; + else + s = soap->tag; + if ((t = strchr(tag, ':'))) + t++; + else + t = tag; + if (!SOAP_STRCMP(s, t)) + return SOAP_OK; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element tag name does not match\n")); + return soap->error = SOAP_SYNTAX_ERROR; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char * +SOAP_FMAC2 +soap_attr_value(struct soap *soap, const char *name, int flag) +{ register struct soap_attribute *tp; + for (tp = soap->attributes; tp; tp = tp->next) + if (!soap_match_tag(soap, tp->name, name)) + break; + if (tp && tp->visible == 2) + { if (flag == 2 && (soap->mode & SOAP_XML_STRICT)) + soap->error = SOAP_PROHIBITED; + else + return tp->value; + } + else if (flag == 1 && (soap->mode & SOAP_XML_STRICT)) + soap->error = SOAP_REQUIRED; + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_attr(struct soap *soap, const char *name, const char *value) +{ register struct soap_attribute *tp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set attribute %s='%s'\n", name, value?value:"")); + for (tp = soap->attributes; tp; tp = tp->next) + { if (!strcmp(tp->name, name)) + break; + } + if (!tp) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute %s\n", name)); + if (!(tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(name)))) + return soap->error = SOAP_EOM; + tp->ns = NULL; +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { struct soap_attribute **tpp = &soap->attributes; + const char *s = strchr(name, ':'); + if (!strncmp(name, "xmlns", 5)) + { for (; *tpp; tpp = &(*tpp)->next) + if (strncmp((*tpp)->name, "xmlns", 5) || strcmp((*tpp)->name + 5, name + 5) > 0) + break; + } + else if (!s) + { for (; *tpp; tpp = &(*tpp)->next) + if (strncmp((*tpp)->name, "xmlns", 5) && ((*tpp)->ns || strcmp((*tpp)->name, name) > 0)) + break; + } + else + { int k; + for (; *tpp; tpp = &(*tpp)->next) + { if (!strncmp((*tpp)->name, "xmlns:", 6) && !strncmp((*tpp)->name + 6, name, s - name) && !(*tpp)->name[6 + s - name]) + { if (!tp->ns) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Canonicalization: prefix %s=%p(%s)\n", name, (*tpp)->ns, (*tpp)->ns)); + tp->ns = (*tpp)->ns; + } + } + else if (strncmp((*tpp)->name, "xmlns", 5) && (*tpp)->ns && tp->ns && ((k = strcmp((*tpp)->ns, tp->ns)) > 0 || (!k && strcmp((*tpp)->name, name) > 0))) + break; + } + } + tp->next = *tpp; + *tpp = tp; + } + else +#endif + { tp->next = soap->attributes; + soap->attributes = tp; + } + strcpy(tp->name, name); + tp->value = NULL; + } + else if (value && tp->value && tp->size <= strlen(value)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute value of %s (free %p)\n", name, tp->value)); + SOAP_FREE(soap, tp->value); + tp->value = NULL; + tp->ns = NULL; + } + if (value) + { if (!tp->value) + { tp->size = strlen(value) + 1; + if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size))) + return soap->error = SOAP_EOM; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute value of %s (%p)\n", tp->name, tp->value)); + } + strcpy(tp->value, value); + if (!strncmp(tp->name, "xmlns:", 6)) + tp->ns = tp->value; + tp->visible = 2; +#ifndef WITH_LEAN + if (!strcmp(name, "wsu:Id")) + { soap->part = SOAP_BEGIN_SECURITY; + strncpy(soap->id, value, sizeof(soap->id)); + soap->id[sizeof(soap->id)-1] = '\0'; + } +#endif + } + else + tp->visible = 1; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_clr_attr(struct soap *soap) +{ register struct soap_attribute *tp; +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { while (soap->attributes) + { tp = soap->attributes->next; + SOAP_FREE(soap, soap->attributes->value); + SOAP_FREE(soap, soap->attributes); + soap->attributes = tp; + } + } + else +#endif + { for (tp = soap->attributes; tp; tp = tp->next) + tp->visible = 0; + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +static int +soap_getattrval(struct soap *soap, char *s, size_t n, soap_wchar d) +{ size_t i; + soap_wchar c; + for (i = 0; i < n; i++) + { c = soap_getutf8(soap); + switch (c) + { + case SOAP_TT: + *s++ = '<'; + soap_unget(soap, '/'); + break; + case SOAP_LT: + *s++ = '<'; + break; + case SOAP_GT: + if (d == ' ') + { soap_unget(soap, c); + *s = '\0'; + return SOAP_OK; + } + *s++ = '>'; + break; + case SOAP_QT: + if (c == d) + { *s = '\0'; + return SOAP_OK; + } + *s++ = '"'; + break; + case SOAP_AP: + if (c == d) + { *s = '\0'; + return SOAP_OK; + } + *s++ = '\''; + break; + case '\t': + case '\n': + case '\r': + case ' ': + case '/': + if (d == ' ') + { soap_unget(soap, c); + *s = '\0'; + return SOAP_OK; + } + default: + if ((int)c == EOF) + return soap->error = SOAP_EOF; + *s++ = (char)c; + } + } + return soap->error = SOAP_EOM; +} +#endif + +/******************************************************************************/ +#ifdef WITH_FAST +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_store_lab(struct soap *soap, const char *s, size_t n) +{ soap->labidx = 0; + return soap_append_lab(soap, s, n); +} +#endif +#endif + +/******************************************************************************/ +#ifdef WITH_FAST +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_append_lab(struct soap *soap, const char *s, size_t n) +{ if (soap->labidx + n >= soap->lablen) + { register char *t = soap->labbuf; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enlarging look-aside buffer to append data, old size=%lu", (unsigned long)soap->lablen)); + if (soap->lablen == 0) + soap->lablen = SOAP_LABLEN; + while (soap->labidx + n >= soap->lablen) + soap->lablen <<= 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, ", new size=%lu\n", (unsigned long)soap->lablen)); + soap->labbuf = (char*)SOAP_MALLOC(soap, soap->lablen); + if (!soap->labbuf) + { if (t) + SOAP_FREE(soap, t); + return soap->error = SOAP_EOM; + } + if (t) + { memcpy(soap->labbuf, t, soap->labidx); + SOAP_FREE(soap, t); + } + } + if (s) + { memcpy(soap->labbuf + soap->labidx, s, n); + soap->labidx += n; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_peek_element(struct soap *soap) +{ +#ifdef WITH_DOM + register struct soap_dom_attribute **att = NULL; + register char *lead = NULL; +#endif + register struct soap_attribute *tp; + const char *t; + register char *s; + register soap_wchar c; + register int i; + if (soap->peeked) + { if (!*soap->tag) + return soap->error = SOAP_NO_TAG; + return SOAP_OK; + } + soap->peeked = 1; + for (;;) + { c = soap_getutf8(soap); + if (c == SOAP_BOM) + c = soap_get(soap); +#ifdef WITH_DOM + /* whitespace leading to start tag is not insignificant for DOM */ + if (soap_blank(c)) + { soap->labidx = 0; + do + { if (soap_append_lab(soap, NULL, 0)) + return SOAP_EOM; + s = soap->labbuf + soap->labidx; + i = soap->lablen - soap->labidx; + soap->labidx = soap->lablen; + while (soap_blank(c) && i--) + { *s++ = c; + c = soap_get(soap); + } + } + while (soap_blank(c)); + *s = '\0'; + lead = soap_strdup(soap, soap->labbuf); + } +#else + while (soap_blank(c)) + c = soap_get(soap); +#endif + if (c != SOAP_LT) + { *soap->tag = '\0'; + if ((int)c == EOF) + return soap->error = SOAP_EOF; + soap_unget(soap, c); +#ifdef WITH_DOM + /* whitespace leading to end tag is not insignificant for DOM */ + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + soap->dom->tail = soap_strdup(soap, lead); +#endif + return soap->error = SOAP_NO_TAG; + } + s = soap->tag; + do c = soap_getutf8(soap); + while (soap_blank(c)); + i = sizeof(soap->tag); + while (c != '/' && soap_notblank(c)) + { if (--i > 0) + *s++ = (char)c; + c = soap_getutf8(soap); + } + while (soap_blank(c)) + c = soap_get(soap); + *s = '\0'; + if (*soap->tag != '?') + break; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "XML PI <%s?>\n", soap->tag)); + while ((int)c != EOF && c != SOAP_GT && c != '?') + { s = soap->tmpbuf; + i = sizeof(soap->tmpbuf) - 2; + while (c != '=' && c != SOAP_GT && c != '?' && soap_notblank(c)) + { if (--i > 0) + *s++ = (char)c; + c = soap_get(soap); + } + while (soap_blank(c)) + c = soap_get(soap); + if (c == '=') + { *s++ = '='; + do c = soap_get(soap); + while (soap_blank(c)); + if (c != SOAP_QT && c != SOAP_AP) + { soap_unget(soap, c); + c = ' '; /* blank delimiter */ + } + if (soap_getattrval(soap, s, i, c) == SOAP_EOM) + { while (soap_getattrval(soap, soap->tmpbuf, sizeof(soap->tmpbuf), c) == SOAP_EOM) + ; + } + else if (!strcmp(soap->tag, "?xml") + && (!soap_tag_cmp(soap->tmpbuf, "encoding=iso-8859-1") + || !soap_tag_cmp(soap->tmpbuf, "encoding=latin1"))) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "XML latin1 encoding\n")); + soap->mode |= SOAP_ENC_LATIN; + } + } + do c = soap_get(soap); + while (soap_blank(c)); + } + } + soap->id[0] = '\0'; + soap->href[0] = '\0'; + soap->type[0] = '\0'; + soap->arrayType[0] = '\0'; + soap->arraySize[0] = '\0'; + soap->arrayOffset[0] = '\0'; + soap->other = 0; + soap->root = -1; + soap->position = 0; + soap->null = 0; + soap->mustUnderstand = 0; +#ifdef WITH_DOM + if (soap->mode & SOAP_XML_DOM) + { register struct soap_dom_element *elt; + elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element)); + if (!elt) + return soap->error = SOAP_EOM; + elt->next = NULL; + elt->nstr = NULL; + elt->name = soap_strdup(soap, soap->tag); + elt->prnt = soap->dom; + elt->elts = NULL; + elt->atts = NULL; + elt->data = NULL; + elt->wide = NULL; + elt->type = 0; + elt->node = NULL; + elt->head = lead; + elt->tail = NULL; + elt->soap = soap; + if (soap->dom) + { struct soap_dom_element *p = soap->dom->elts; + if (p) + { while (p->next) + p = p->next; + p->next = elt; + } + else + soap->dom->elts = elt; + } + soap->dom = elt; + att = &elt->atts; + } +#endif + for (tp = soap->attributes; tp; tp = tp->next) + tp->visible = 0; + while ((int)c != EOF && c != SOAP_GT && c != '/') + { s = soap->tmpbuf; + i = sizeof(soap->tmpbuf); + while (c != '=' && c != '/' && soap_notblank(c)) + { if (--i > 0) + *s++ = (char)c; + c = soap_get(soap); + } + *s = '\0'; + if (i == sizeof(soap->tmpbuf)) + return soap->error = SOAP_SYNTAX_ERROR; +#ifdef WITH_DOM + /* add attribute name to dom */ + if (att) + { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); + if (!*att) + return soap->error = SOAP_EOM; + (*att)->next = NULL; + (*att)->nstr = NULL; + (*att)->name = soap_strdup(soap, soap->tmpbuf); + (*att)->data = NULL; + (*att)->wide = NULL; + (*att)->soap = soap; + } +#endif + if (!strncmp(soap->tmpbuf, "xmlns", 5)) + { if (soap->tmpbuf[5] == ':') + { soap->tmpbuf[5] = '\0'; + t = soap->tmpbuf + 6; + } + else if (soap->tmpbuf[5]) + t = NULL; + else + t = SOAP_STR_EOS; + } + else + t = NULL; + for (tp = soap->attributes; tp; tp = tp->next) + { if (!SOAP_STRCMP(tp->name, soap->tmpbuf)) + break; + } + if (!tp) + { tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(soap->tmpbuf)); + if (!tp) + return soap->error = SOAP_EOM; + strcpy(tp->name, soap->tmpbuf); + tp->value = NULL; + tp->size = 0; + tp->next = soap->attributes; + soap->attributes = tp; + } + while (soap_blank(c)) + c = soap_get(soap); + if (c == '=') + { do c = soap_get(soap); + while (soap_blank(c)); + if (c != SOAP_QT && c != SOAP_AP) + { soap_unget(soap, c); + c = ' '; /* blank delimiter */ + } + if (soap_getattrval(soap, tp->value, tp->size, c)) + { +#ifdef WITH_FAST + if (soap->error != SOAP_EOM) + return soap->error; + soap->error = SOAP_OK; + if (soap_store_lab(soap, tp->value, tp->size)) + return soap->error; + if (tp->value) + SOAP_FREE(soap, tp->value); + for (;;) + { if (soap_getattrval(soap, soap->labbuf + soap->labidx, soap->lablen - soap->labidx, c)) + { if (soap->error != SOAP_EOM) + return soap->error; + soap->error = SOAP_OK; + soap->labidx = soap->lablen; + if (soap_append_lab(soap, NULL, 0)) + return soap->error; + } + else + break; + } + if (soap->labidx) + tp->size = soap->lablen; + else + { tp->size = strlen(soap->labbuf) + 1; + if (tp->size < SOAP_LABLEN) + tp->size = SOAP_LABLEN; + } + if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size))) + return soap->error = SOAP_EOM; + strcpy(tp->value, soap->labbuf); +#else + size_t n; + if (soap->error != SOAP_EOM) + return soap->error; + soap->error = SOAP_OK; + if (soap_new_block(soap)) + return soap->error; + for (;;) + { if (!(s = (char*)soap_push_block(soap, SOAP_BLKLEN))) + return soap->error; + if (soap_getattrval(soap, s, SOAP_BLKLEN, c)) + { if (soap->error != SOAP_EOM) + return soap->error; + soap->error = SOAP_OK; + } + else + break; + } + n = tp->size + soap->blist->size; + if (!(s = (char*)SOAP_MALLOC(soap, n))) + return soap->error = SOAP_EOM; + if (tp->value) + { memcpy(s, tp->value, tp->size); + SOAP_FREE(soap, tp->value); + } + soap_save_block(soap, s + tp->size, 0); + tp->value = s; + tp->size = n; +#endif + } + do c = soap_get(soap); + while (soap_blank(c)); + tp->visible = 2; /* seen this attribute w/ value */ +#ifdef WITH_DOM + if (att) + (*att)->data = soap_strdup(soap, tp->value); +#endif + } + else + tp->visible = 1; /* seen this attribute w/o value */ +#ifdef WITH_DOM + if (att) + att = &(*att)->next; +#endif + if (t && tp->value) + { if (soap_push_namespace(soap, t, tp->value)) + return soap->error; + tp->visible = 0; + } + } +#ifdef WITH_DOM + if (att) + { soap->dom->nstr = soap_dom_current_nstr(soap, soap->tag); + for (att = &soap->dom->atts; *att; att = &(*att)->next) + (*att)->nstr = soap_dom_current_nstr(soap, (*att)->name); + } +#endif + if ((int)c == EOF) + return soap->error = SOAP_EOF; + if (!(soap->body = (c != '/'))) + do c = soap_get(soap); + while (soap_blank(c)); +#ifdef WITH_DOM + if (soap->mode & SOAP_XML_DOM) + { if (!soap->body && soap->dom->prnt) + soap->dom = soap->dom->prnt; + } +#endif + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible && tp->value) + { if (!strcmp(tp->name, "id")) + { *soap->id = '#'; + strncpy(soap->id + 1, tp->value, sizeof(soap->id) - 2); + soap->id[sizeof(soap->id)-1] = '\0'; + } + else if (!strcmp(tp->name, "href")) + { strncpy(soap->href, tp->value, sizeof(soap->href) - 1); + soap->href[sizeof(soap->href)-1] = '\0'; + } + else if ((soap->version == 2 || (soap->mode & SOAP_XML_GRAPH)) && !strcmp(tp->name, "ref")) + { *soap->href = '#'; + strncpy(soap->href + 1, tp->value, sizeof(soap->href) - 2); + soap->href[sizeof(soap->href)-1] = '\0'; + } + else if (!soap_match_tag(soap, tp->name, "xsi:type")) + { strncpy(soap->type, tp->value, sizeof(soap->type) - 1); + soap->type[sizeof(soap->type)-1] = '\0'; + } + else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:arrayType")) + { s = soap_strrchr(tp->value, '['); + if (s && (size_t)(s - tp->value) < sizeof(soap->arrayType)) + { strncpy(soap->arrayType, tp->value, s - tp->value); + soap->arrayType[s - tp->value] = '\0'; + strncpy(soap->arraySize, s, sizeof(soap->arraySize) - 1); + } + else + strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1); + soap->arraySize[sizeof(soap->arrayType)-1] = '\0'; + soap->arrayType[sizeof(soap->arrayType)-1] = '\0'; + } + else if (soap->version == 2 && !soap_match_tag(soap, tp->name, "SOAP-ENC:itemType")) + strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1); + else if (soap->version == 2 && !soap_match_tag(soap, tp->name, "SOAP-ENC:arraySize")) + strncpy(soap->arraySize, tp->value, sizeof(soap->arraySize) - 1); + else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:offset")) + strncpy(soap->arrayOffset, tp->value, sizeof(soap->arrayOffset)); + else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:position")) + soap->position = soap_getposition(tp->value, soap->positions); + else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:root")) + soap->root = ((!strcmp(tp->value, "1") || !strcmp(tp->value, "true"))); + else if ((soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENV:actor")) + || (soap->version == 2 && !soap_match_tag(soap, tp->name, "SOAP-ENV:role"))) + { if ((!soap->actor || strcmp(soap->actor, tp->value)) + && strcmp(tp->value, "http://schemas.xmlsoap.org/soap/actor/next") + && strcmp(tp->value, "http://www.w3.org/2003/05/soap-envelope/role/next")) + soap->other = 1; + } + else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand") + && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true"))) + soap->mustUnderstand = 1; + else if ((!soap_match_tag(soap, tp->name, "xsi:null") + || !soap_match_tag(soap, tp->name, "xsi:nil")) + && (!strcmp(tp->value, "1") + || !strcmp(tp->value, "true"))) + soap->null = 1; + } + } + return soap->error = SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_retry(struct soap *soap) +{ soap->error = SOAP_OK; + soap_revert(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_revert(struct soap *soap) +{ if (!soap->peeked) + { soap->peeked = 1; + if (soap->body) + soap->level--; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reverting last element (level=%u)\n", soap->level)); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_string_out(struct soap *soap, const char *s, int flag) +{ register const char *t; + register soap_wchar c; + register soap_wchar mask = 0xFFFFFF80UL; +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { soap->dom->data = soap_strdup(soap, s); + return SOAP_OK; + } +#endif + if (soap->mode & SOAP_C_UTFSTRING) + mask = 0; + t = s; + while ((c = *t++)) + { switch (c) + { + case 9: + if (flag) + { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, " ", 5)) + return soap->error; + s = t; + } + break; + case 10: + if (flag || !(soap->mode & SOAP_XML_CANONICAL)) + { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, " ", 5)) + return soap->error; + s = t; + } + break; + case 13: + if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, " ", 5)) + return soap->error; + s = t; + break; + case '&': + if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&", 5)) + return soap->error; + s = t; + break; + case '<': + if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "<", 4)) + return soap->error; + s = t; + break; + case '>': + if (!flag) + { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, ">", 4)) + return soap->error; + s = t; + } + break; + case '"': + if (flag) + { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, """, 6)) + return soap->error; + s = t; + } + break; + default: +#ifndef WITH_LEANER +#ifdef HAVE_MBTOWC + if (soap->mode & SOAP_C_MBSTRING) + { wchar_t wc; + register int m = mbtowc(&wc, t - 1, MB_CUR_MAX); + if (m > 0 && wc != c) + { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, wc)) + return soap->error; + s = t += m - 1; + continue; + } + } +#endif +#endif + if (c & mask) + { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned char)c)) + return soap->error; + s = t; + } + } + } + return soap_send_raw(soap, s, t - s - 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_string_in(struct soap *soap, int flag, long minlen, long maxlen) +{ register char *s; + char *t = NULL; + register size_t i; + register long l = 0; + register int n = 0; + register int m = 0; + register soap_wchar c; +#if !defined(WITH_LEANER) && defined(HAVE_WCTOMB) + char buf[MB_LEN_MAX > 8 ? MB_LEN_MAX : 8]; +#else + char buf[8]; +#endif + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading string content\n")); + if (soap->peeked) + { if (!soap->body) + return NULL; + if (*soap->tag) + { n = 1; + soap->peeked = 0; +#ifndef WITH_LEAN + t = soap->tmpbuf; + t[0] = '<'; + strncpy(t + 1, soap->tag, sizeof(soap->tmpbuf) - 1); + strncat(t, ">", sizeof(soap->tmpbuf)); + m = strlen(soap->tag) + 2; +#endif + } + } +#ifdef WITH_CDATA + if (!flag) + { register int state = 0; +#ifdef WITH_FAST + soap->labidx = 0; /* use look-aside buffer */ +#else + if (soap_new_block(soap)) + return NULL; +#endif + for (;;) + { +#ifdef WITH_FAST + register size_t k; + if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */ + return NULL; + s = soap->labbuf + soap->labidx; /* space to populate */ + k = soap->lablen - soap->labidx; /* number of bytes available */ + soap->labidx = soap->lablen; /* claim this space */ +#else + register size_t k = SOAP_BLKLEN; + if (!(s = (char*)soap_push_block(soap, k))) + return NULL; +#endif + for (i = 0; i < k; i++) + { if (m > 0) + { *s++ = *t++; /* copy multibyte characters */ + m--; + continue; + } + c = soap_getchar(soap); + if ((int)c == EOF) + goto end; + if (c >= 0x80 && !(soap->mode & SOAP_ENC_LATIN)) + { soap_unget(soap, c); + c = soap_getutf8(soap); + if (soap->mode & SOAP_C_UTFSTRING) + { if ((c & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP) + { c &= 0x7FFFFFFF; + t = buf; + if (c < 0x0800) + *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); + else + { if (c < 0x010000) + *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + else + { if (c < 0x200000) + *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + else + { if (c < 0x04000000) + *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + else + { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + } + *t++ = (char)(0x80 | (c & 0x3F)); + m = (int)(t - buf) - 1; + t = buf; + *s++ = *t++; + continue; + } + } + } + switch (state) + { case 1: + if (c == ']') + state = 4; + *s++ = c; + continue; + case 2: + if (c == '-') + state = 6; + *s++ = c; + continue; + case 3: + if (c == '?') + state = 8; + *s++ = c; + continue; + /* CDATA */ + case 4: + if (c == ']') + state = 5; + else + state = 1; + *s++ = c; + continue; + case 5: + if (c == '>') + state = 0; + else + state = 1; + *s++ = c; + continue; + /* comment */ + case 6: + if (c == '-') + state = 7; + else + state = 2; + *s++ = c; + continue; + case 7: + if (c == '>') + state = 0; + else + state = 2; + *s++ = c; + continue; + /* PI */ + case 8: + if (c == '>') + state = 0; + else + state = 3; + *s++ = c; + continue; + } + switch (c) + { + case '/': + if (n > 0) + { c = soap_getchar(soap); + if (c == '>') + n--; + soap_unget(soap, c); + } + *s++ = '/'; + break; + case '<': + c = soap_getchar(soap); + if (c == '/') + { if (n == 0) + { c = SOAP_TT; + goto end; + } + n--; + } + else if (c == '!') + { c = soap_getchar(soap); + if (c == '[') + { do c = soap_getchar(soap); + while ((int)c != EOF && c != '['); + if ((int)c == EOF) + goto end; + t = (char*)"![CDATA["; + m = 8; + state = 1; + } + else if (c == '-') + { if ((c = soap_getchar(soap)) == '-') + state = 2; + t = (char*)"!-"; + m = 2; + soap_unget(soap, c); + } + else + { t = (char*)"!"; + m = 1; + soap_unget(soap, c); + } + *s++ = '<'; + break; + } + else if (c == '?') + state = 3; + else + n++; + soap_unget(soap, c); + *s++ = '<'; + break; + case '>': + *s++ = '>'; + break; + case '"': + *s++ = '"'; + break; + default: +#ifndef WITH_LEANER +#ifdef HAVE_WCTOMB + if (soap->mode & SOAP_C_MBSTRING) + { m = wctomb(buf, c & 0x7FFFFFFF); + if (m >= 1 && m <= (int)MB_CUR_MAX) + { t = buf; + *s++ = *t++; + m--; + } + else + { *s++ = SOAP_UNKNOWN_CHAR; + m = 0; + } + } + else +#endif +#endif + *s++ = (char)(c & 0xFF); + } + l++; + if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); + soap->error = SOAP_LENGTH; + return NULL; + } + } + } + } +#endif +#ifdef WITH_FAST + soap->labidx = 0; /* use look-aside buffer */ +#else + if (soap_new_block(soap)) + return NULL; +#endif + for (;;) + { +#ifdef WITH_FAST + register size_t k; + if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */ + return NULL; + s = soap->labbuf + soap->labidx; /* space to populate */ + k = soap->lablen - soap->labidx; /* number of bytes available */ + soap->labidx = soap->lablen; /* claim this space */ +#else + register size_t k = SOAP_BLKLEN; + if (!(s = (char*)soap_push_block(soap, k))) + return NULL; +#endif + for (i = 0; i < k; i++) + { if (m > 0) + { *s++ = *t++; /* copy multibyte characters */ + m--; + continue; + } + if (soap->mode & SOAP_C_UTFSTRING) + { if (((c = soap_get(soap)) & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP) + { c &= 0x7FFFFFFF; + t = buf; + if (c < 0x0800) + *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); + else + { if (c < 0x010000) + *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + else + { if (c < 0x200000) + *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + else + { if (c < 0x04000000) + *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + else + { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + } + *t++ = (char)(0x80 | (c & 0x3F)); + m = (int)(t - buf) - 1; + t = buf; + *s++ = *t++; + continue; + } + } + else + c = soap_getutf8(soap); + switch (c) + { + case SOAP_TT: + if (n == 0) + goto end; + n--; + *s++ = '<'; + t = (char*)"/"; + m = 1; + break; + case SOAP_LT: + n++; + *s++ = '<'; + break; + case SOAP_GT: + *s++ = '>'; + break; + case SOAP_QT: + *s++ = '"'; + break; + case SOAP_AP: + *s++ = '\''; + break; + case '/': + if (n > 0) + { c = soap_get(soap); + if (c == SOAP_GT) + n--; + soap_unget(soap, c); + } + *s++ = '/'; + break; + case '<' | 0x80000000: + if (flag) + *s++ = '<'; + else + { *s++ = '&'; + t = (char*)"lt;"; + m = 3; + } + break; + case '>' | 0x80000000: + if (flag) + *s++ = '>'; + else + { *s++ = '&'; + t = (char*)"gt;"; + m = 3; + } + break; + case '&' | 0x80000000: + if (flag) + *s++ = '&'; + else + { *s++ = '&'; + t = (char*)"amp;"; + m = 4; + } + break; + case '"' | 0x80000000: + if (flag) + *s++ = '"'; + else + { *s++ = '&'; + t = (char*)"quot;"; + m = 5; + } + break; + case '\'' | 0x80000000: + if (flag) + *s++ = '\''; + else + { *s++ = '&'; + t = (char*)"apos;"; + m = 5; + } + break; + default: + if ((int)c == EOF) + goto end; +#ifndef WITH_LEANER +#ifdef HAVE_WCTOMB + if (soap->mode & SOAP_C_MBSTRING) + { m = wctomb(buf, c & 0x7FFFFFFF); + if (m >= 1 && m <= (int)MB_CUR_MAX) + { t = buf; + *s++ = *t++; + m--; + } + else + { *s++ = SOAP_UNKNOWN_CHAR; + m = 0; + } + } + else +#endif +#endif + *s++ = (char)(c & 0xFF); + } + l++; + if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); + soap->error = SOAP_LENGTH; + return NULL; + } + } + } +end: + soap_unget(soap, c); + *s = '\0'; +#ifdef WITH_FAST + t = soap_strdup(soap, soap->labbuf); +#else + soap_size_block(soap, i+1); + t = soap_save_block(soap, NULL, 0); +#endif + if ((soap->mode & SOAP_XML_STRICT) && l < minlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen)); + soap->error = SOAP_LENGTH; + return NULL; + } +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { if (flag == 3) + soap->dom->tail = t; + else + soap->dom->data = t; + } +#endif + if (flag == 2) + if (soap_s2QName(soap, t, &t)) + return NULL; + return t; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_wstring_out(struct soap *soap, const wchar_t *s, int flag) +{ const char *t; + char tmp; + register soap_wchar c; +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { wchar_t *r = (wchar_t*)s; + int n = 1; + while (*r++) + n++; + soap->dom->wide = r = (wchar_t*)soap_malloc(soap, n * sizeof(wchar_t)); + while (n--) + *r++ = *s++; + return SOAP_OK; + } +#endif + while ((c = *s++)) + { switch (c) + { + case 9: + if (flag) + t = " "; + else + t = "\t"; + break; + case 10: + if (flag || !(soap->mode & SOAP_XML_CANONICAL)) + t = " "; + else + t = "\n"; + break; + case 13: + t = " "; + break; + case '&': + t = "&"; + break; + case '<': + t = "<"; + break; + case '>': + if (flag) + t = ">"; + else + t = ">"; + break; + case '"': + if (flag) + t = """; + else + t = "\""; + break; + default: + if (c > 0 && c < 0x80) + { tmp = (char)c; + if (soap_send_raw(soap, &tmp, 1)) + return soap->error; + } + else if (soap_pututf8(soap, (unsigned long)c)) + return soap->error; + continue; + } + if (soap_send(soap, t)) + return soap->error; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +wchar_t * +SOAP_FMAC2 +soap_wstring_in(struct soap *soap, int flag, long minlen, long maxlen) +{ wchar_t *s; + register int i, n = 0; + register long l = 0; + register soap_wchar c; + const char *t = NULL; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading wide string content\n")); + if (soap->peeked) + { if (!soap->body) + return NULL; + if (*soap->tag) + { n = 1; + soap->peeked = 0; + } + } + if (soap_new_block(soap)) + return NULL; + for (;;) + { if (!(s = (wchar_t*)soap_push_block(soap, sizeof(wchar_t)*SOAP_BLKLEN))) + return NULL; + for (i = 0; i < SOAP_BLKLEN; i++) + { if (t) + { *s++ = (wchar_t)*t++; + if (!*t) + t = NULL; + continue; + } + c = soap_getutf8(soap); + switch (c) + { + case SOAP_TT: + if (n == 0) + goto end; + n--; + *s++ = '<'; + soap_unget(soap, '/'); + break; + case SOAP_LT: + n++; + *s++ = '<'; + break; + case SOAP_GT: + *s++ = '>'; + break; + case SOAP_QT: + *s++ = '"'; + break; + case SOAP_AP: + *s++ = '\''; + break; + case '/': + if (n > 0) + { c = soap_getutf8(soap); + if (c == SOAP_GT) + n--; + soap_unget(soap, c); + } + *s++ = '/'; + break; + case '<': + if (flag) + *s++ = (soap_wchar)'<'; + else + { *s++ = (soap_wchar)'&'; + t = "lt;"; + } + break; + case '>': + if (flag) + *s++ = (soap_wchar)'>'; + else + { *s++ = (soap_wchar)'&'; + t = "gt;"; + } + break; + case '"': + if (flag) + *s++ = (soap_wchar)'"'; + else + { *s++ = (soap_wchar)'&'; + t = "quot;"; + } + break; + default: + if ((int)c == EOF) + goto end; + *s++ = (wchar_t)c & 0x7FFFFFFF; + } + l++; + if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); + soap->error = SOAP_LENGTH; + return NULL; + } + } + } +end: + soap_unget(soap, c); + *s = '\0'; + soap_size_block(soap, sizeof(wchar_t) * (i + 1)); + if ((soap->mode & SOAP_XML_STRICT) && l < minlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen)); + soap->error = SOAP_LENGTH; + return NULL; + } + s = (wchar_t*)soap_save_block(soap, NULL, 0); +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + soap->dom->wide = s; +#endif + return s; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_int2s(struct soap *soap, int n) +{ return soap_long2s(soap, (long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outint(struct soap *soap, const char *tag, int id, const int *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_long2s(soap, (long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2int(struct soap *soap, const char *s, int *p) +{ if (s) + { char *r; + *p = (int)soap_strtol(s, &r, 10); + if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r +#ifndef WITH_NOIO +#ifndef WITH_LEAN + || soap_errno == SOAP_ERANGE +#endif +#endif + ) + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int * +SOAP_FMAC2 +soap_inint(struct soap *soap, const char *tag, int *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":int") + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (int*)soap_id_enter(soap, soap->id, p, t, sizeof(int), 0, NULL, NULL, NULL); + if (*soap->href) + p = (int*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(int), 0, NULL); + else if (p) + { if (soap_s2int(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_long2s(struct soap *soap, long n) +{ sprintf(soap->tmpbuf, "%ld", n); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outlong(struct soap *soap, const char *tag, int id, const long *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_long2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2long(struct soap *soap, const char *s, long *p) +{ if (s) + { char *r; + *p = soap_strtol(s, &r, 10); + if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r +#ifndef WITH_NOIO +#ifndef WITH_LEAN + || soap_errno == SOAP_ERANGE +#endif +#endif + ) + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +long * +SOAP_FMAC2 +soap_inlong(struct soap *soap, const char *tag, long *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":int") + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (long*)soap_id_enter(soap, soap->id, p, t, sizeof(long), 0, NULL, NULL, NULL); + if (*soap->href) + p = (long*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(long), 0, NULL); + else if (p) + { if (soap_s2long(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_LONG642s(struct soap *soap, LONG64 n) +{ sprintf(soap->tmpbuf, SOAP_LONG_FORMAT, n); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outLONG64(struct soap *soap, const char *tag, int id, const LONG64 *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_LONG642s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2LONG64(struct soap *soap, const char *s, LONG64 *p) +{ if (s) + { +#ifdef HAVE_STRTOLL + char *r; + *p = strtoll(s, &r, 10); + if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r +#ifndef WITH_NOIO +#ifndef WITH_LEAN + || soap_errno == SOAP_ERANGE +#endif +#endif + ) +#else +# ifdef HAVE_SSCANF + if (sscanf(s, SOAP_LONG_FORMAT, p) != 1) +# endif +#endif + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +LONG64 * +SOAP_FMAC2 +soap_inLONG64(struct soap *soap, const char *tag, LONG64 *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":integer") + && soap_match_tag(soap, soap->type, ":positiveInteger") + && soap_match_tag(soap, soap->type, ":negativeInteger") + && soap_match_tag(soap, soap->type, ":nonPositiveInteger") + && soap_match_tag(soap, soap->type, ":nonNegativeInteger") + && soap_match_tag(soap, soap->type, ":long") + && soap_match_tag(soap, soap->type, ":int") + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (LONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(LONG64), 0, NULL, NULL, NULL); + if (*soap->href) + p = (LONG64*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(LONG64), 0, NULL); + else if (p) + { if (soap_s2LONG64(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_byte2s(struct soap *soap, char n) +{ return soap_long2s(soap, (long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outbyte(struct soap *soap, const char *tag, int id, const char *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_long2s(soap, (long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2byte(struct soap *soap, const char *s, char *p) +{ if (s) + { long n; + char *r; + n = soap_strtol(s, &r, 10); + if (s == r || *r || n < -128 || n > 127) + soap->error = SOAP_TYPE; + *p = (char)n; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_inbyte(struct soap *soap, const char *tag, char *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (char*)soap_id_enter(soap, soap->id, p, t, sizeof(char), 0, NULL, NULL, NULL); + if (*soap->href) + p = (char*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(char), 0, NULL); + else if (p) + { if (soap_s2byte(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_short2s(struct soap *soap, short n) +{ return soap_long2s(soap, (long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outshort(struct soap *soap, const char *tag, int id, const short *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_long2s(soap, (long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2short(struct soap *soap, const char *s, short *p) +{ if (s) + { long n; + char *r; + n = soap_strtol(s, &r, 10); + if (s == r || *r || n < -32768 || n > 32767) + soap->error = SOAP_TYPE; + *p = (short)n; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +short * +SOAP_FMAC2 +soap_inshort(struct soap *soap, const char *tag, short *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (short*)soap_id_enter(soap, soap->id, p, t, sizeof(short), 0, NULL, NULL, NULL); + if (*soap->href) + p = (short*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(short), 0, NULL); + else if (p) + { if (soap_s2short(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_float2s(struct soap *soap, float n) +{ const char *s; + if (soap_isnan((double)n)) + s = "NaN"; + else if (soap_ispinff(n)) + s = "INF"; + else if (soap_isninff(n)) + s = "-INF"; + else + { sprintf(soap->tmpbuf, soap->float_format, n); + s = soap->tmpbuf; + } + return s; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outfloat(struct soap *soap, const char *tag, int id, const float *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_float2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2float(struct soap *soap, const char *s, float *p) +{ if (s) + { if (!*s) + return soap->error = SOAP_TYPE; + if (!soap_tag_cmp(s, "INF")) + *p = FLT_PINFTY; + else if (!soap_tag_cmp(s, "+INF")) + *p = FLT_PINFTY; + else if (!soap_tag_cmp(s, "-INF")) + *p = FLT_NINFTY; + else if (!soap_tag_cmp(s, "NaN")) + *p = FLT_NAN; + else + { +/* On some systems, strtof appears to be broken or doesn't link: use with caution */ +#if defined(HAVE_STRTOF) + char *r; + *p = strtof((char*)s, &r); + if (*r) +#elif defined(HAVE_STRTOD) + char *r; + *p = (float)strtod(s, &r); + if (*r) +#endif +#ifdef HAVE_SSCANF + if (sscanf(s, "%g", p) != 1) + soap->error = SOAP_TYPE; +#else + soap->error = SOAP_TYPE; +#endif + } + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static int soap_isnumeric(struct soap *soap, const char *type) +{ if (soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":float") + && soap_match_tag(soap, soap->type, ":double") + && soap_match_tag(soap, soap->type, ":decimal") + && soap_match_tag(soap, soap->type, ":integer") + && soap_match_tag(soap, soap->type, ":positiveInteger") + && soap_match_tag(soap, soap->type, ":negativeInteger") + && soap_match_tag(soap, soap->type, ":nonPositiveInteger") + && soap_match_tag(soap, soap->type, ":nonNegativeInteger") + && soap_match_tag(soap, soap->type, ":long") + && soap_match_tag(soap, soap->type, ":int") + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte") + && soap_match_tag(soap, soap->type, ":unsignedLong") + && soap_match_tag(soap, soap->type, ":unsignedInt") + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return SOAP_ERR; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +float * +SOAP_FMAC2 +soap_infloat(struct soap *soap, const char *tag, float *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type != '\0' && soap_isnumeric(soap, type)) + return NULL; +#endif + p = (float*)soap_id_enter(soap, soap->id, p, t, sizeof(float), 0, NULL, NULL, NULL); + if (*soap->href) + p = (float*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(float), 0, NULL); + else if (p) + { if (soap_s2float(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_double2s(struct soap *soap, double n) +{ const char *s; + if (soap_isnan(n)) + s = "NaN"; + else if (soap_ispinfd(n)) + s = "INF"; + else if (soap_isninfd(n)) + s = "-INF"; + else + { sprintf(soap->tmpbuf, soap->double_format, n); + s = soap->tmpbuf; + } + return s; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outdouble(struct soap *soap, const char *tag, int id, const double *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_double2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2double(struct soap *soap, const char *s, double *p) +{ if (s) + { if (!*s) + return soap->error = SOAP_TYPE; + if (!soap_tag_cmp(s, "INF")) + *p = DBL_PINFTY; + else if (!soap_tag_cmp(s, "+INF")) + *p = DBL_PINFTY; + else if (!soap_tag_cmp(s, "-INF")) + *p = DBL_NINFTY; + else if (!soap_tag_cmp(s, "NaN")) + *p = DBL_NAN; + else + { +#ifdef HAVE_STRTOD + char *r; + *p = strtod(s, &r); + if (*r) +#endif +#ifdef HAVE_SSCANF + if (sscanf(s, "%lg", p) != 1) + soap->error = SOAP_TYPE; +#else + soap->error = SOAP_TYPE; +#endif + } + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +double * +SOAP_FMAC2 +soap_indouble(struct soap *soap, const char *tag, double *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type != '\0' && soap_isnumeric(soap, type)) + return NULL; +#endif + p = (double*)soap_id_enter(soap, soap->id, p, t, sizeof(double), 0, NULL, NULL, NULL); + if (*soap->href) + p = (double*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(double), 0, NULL); + else if (p) + { if (soap_s2double(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_unsignedByte2s(struct soap *soap, unsigned char n) +{ return soap_unsignedLong2s(soap, (unsigned long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outunsignedByte(struct soap *soap, const char *tag, int id, const unsigned char *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2unsignedByte(struct soap *soap, const char *s, unsigned char *p) +{ if (s) + { unsigned long n; + char *r; + n = soap_strtoul(s, &r, 10); + if (s == r || *r || n > 255) + soap->error = SOAP_TYPE; + *p = (unsigned char)n; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +unsigned char * +SOAP_FMAC2 +soap_inunsignedByte(struct soap *soap, const char *tag, unsigned char *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (unsigned char*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned char), 0, NULL, NULL, NULL); + if (*soap->href) + p = (unsigned char*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(unsigned char), 0, NULL); + else if (p) + { if (soap_s2unsignedByte(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_unsignedShort2s(struct soap *soap, unsigned short n) +{ return soap_unsignedLong2s(soap, (unsigned long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outunsignedShort(struct soap *soap, const char *tag, int id, const unsigned short *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2unsignedShort(struct soap *soap, const char *s, unsigned short *p) +{ if (s) + { unsigned long n; + char *r; + n = soap_strtoul(s, &r, 10); + if (s == r || *r || n > 65535) + soap->error = SOAP_TYPE; + *p = (unsigned short)n; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +unsigned short * +SOAP_FMAC2 +soap_inunsignedShort(struct soap *soap, const char *tag, unsigned short *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (unsigned short*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned short), 0, NULL, NULL, NULL); + if (*soap->href) + p = (unsigned short*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(unsigned short), 0, NULL); + else if (p) + { if (soap_s2unsignedShort(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_unsignedInt2s(struct soap *soap, unsigned int n) +{ return soap_unsignedLong2s(soap, (unsigned long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outunsignedInt(struct soap *soap, const char *tag, int id, const unsigned int *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2unsignedInt(struct soap *soap, const char *s, unsigned int *p) +{ if (s) + { char *r; + *p = (unsigned int)soap_strtoul(s, &r, 10); + if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r +#ifndef WITH_NOIO +#ifndef WITH_LEAN + || soap_errno == SOAP_ERANGE +#endif +#endif + ) + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +unsigned int * +SOAP_FMAC2 +soap_inunsignedInt(struct soap *soap, const char *tag, unsigned int *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":unsignedInt") + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (unsigned int*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned int), 0, NULL, NULL, NULL); + if (*soap->href) + p = (unsigned int*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(unsigned int), 0, NULL); + else if (p) + { if (soap_s2unsignedInt(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_unsignedLong2s(struct soap *soap, unsigned long n) +{ sprintf(soap->tmpbuf, "%lu", n); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outunsignedLong(struct soap *soap, const char *tag, int id, const unsigned long *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_unsignedLong2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2unsignedLong(struct soap *soap, const char *s, unsigned long *p) +{ if (s) + { char *r; + *p = soap_strtoul(s, &r, 10); + if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r +#ifndef WITH_NOIO +#ifndef WITH_LEAN + || soap_errno == SOAP_ERANGE +#endif +#endif + ) + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +unsigned long * +SOAP_FMAC2 +soap_inunsignedLong(struct soap *soap, const char *tag, unsigned long *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":unsignedInt") + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (unsigned long*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned long), 0, NULL, NULL, NULL); + if (*soap->href) + p = (unsigned long*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(unsigned long), 0, NULL); + else if (p) + { if (soap_s2unsignedLong(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_ULONG642s(struct soap *soap, ULONG64 n) +{ sprintf(soap->tmpbuf, SOAP_ULONG_FORMAT, n); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outULONG64(struct soap *soap, const char *tag, int id, const ULONG64 *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_ULONG642s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2ULONG64(struct soap *soap, const char *s, ULONG64 *p) +{ if (s) + { +#ifdef HAVE_STRTOULL + char *r; + *p = strtoull(s, &r, 10); + if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r +#ifndef WITH_NOIO +#ifndef WITH_LEAN + || soap_errno == SOAP_ERANGE +#endif +#endif + ) +#else +# ifdef HAVE_SSCANF + if (sscanf(s, SOAP_ULONG_FORMAT, p) != 1) +# endif +#endif + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +ULONG64 * +SOAP_FMAC2 +soap_inULONG64(struct soap *soap, const char *tag, ULONG64 *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":positiveInteger") + && soap_match_tag(soap, soap->type, ":nonNegativeInteger") + && soap_match_tag(soap, soap->type, ":unsignedLong") + && soap_match_tag(soap, soap->type, ":unsignedInt") + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } + p = (ULONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(ULONG64), 0, NULL, NULL, NULL); + if (*soap->href) + p = (ULONG64*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(ULONG64), 0, NULL); + else if (p) + { if (soap_s2ULONG64(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2string(struct soap *soap, const char *s, char **t) +{ *t = NULL; + if (s && !(*t = soap_strdup(soap, s))) + soap->error = SOAP_EOM; + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2QName(struct soap *soap, const char *s, char **t) +{ if (s) + { struct soap_nlist *np; + const char *p; + if (!strncmp(s, "xml:", 4)) + { *t = soap_strdup(soap, s); + return SOAP_OK; + } + np = soap->nlist; + p = strchr(s, ':'); + if (p) + { register int n = p - s; + while (np && (strncmp(np->id, s, n) || np->id[n])) + np = np->next; + p++; + } + else + { while (np && *np->id) + np = np->next; + p = s; + } + if (np) + { if (np->index >= 0 && soap->local_namespaces) + { register const char *q = soap->local_namespaces[np->index].id; + if (q) + { if ((*t = (char*)soap_malloc(soap, strlen(p) + strlen(q) + 2))) + sprintf(*t, "%s:%s", q, p); + return SOAP_OK; + } + } + if (np->ns) + { if ((*t = (char*)soap_malloc(soap, strlen(p) + strlen(np->ns) + 4))) + sprintf(*t, "\"%s\":%s", np->ns, p); + return SOAP_OK; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Namespace prefix of '%s' not defined (index=%d, URI=%s)\n", s, np->index, np->ns?np->ns:"")); + return soap->error = SOAP_NAMESPACE; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Namespace prefix of '%s' not defined, assuming empty namespace\n", s)); + if ((*t = (char*)soap_malloc(soap, strlen(p) + 4))) + sprintf(*t, "\"\":%s", p); + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_QName2s(struct soap *soap, const char *s) +{ struct Namespace *p; + char *t; + int n; + if (!s || *s != '"') + { +#ifndef WITH_LEAN + if (s && (soap->mode & SOAP_XML_CANONICAL)) + { t = strchr(s, ':'); + if (t) + soap_utilize_ns(soap, s, t - s); + } +#endif + return s; + } + s++; + if ((p = soap->local_namespaces)) + { for (; p->id; p++) + { if (p->ns) + if (!soap_tag_cmp(s, p->ns)) + break; + if (p->in) + if (!soap_tag_cmp(s, p->in)) + break; + } + if (p && p->id) + { s = strchr(s, '"'); + if (s) + { t = (char*)soap_malloc(soap, strlen(p->id) + strlen(s)); + strcpy(t, p->id); + strcat(t, s + 1); + return t; + } + } + } + t = (char*)strchr(s, '"'); + if (t) + n = t - s; + else + n = 0; + t = soap_strdup(soap, s); + t[n] = '\0'; + sprintf(soap->tmpbuf, "xmlns:_%d", soap->idnum++); + soap_set_attr(soap, soap->tmpbuf, t); + s = strchr(s, '"'); + if (s) + { t = (char*)soap_malloc(soap, strlen(soap->tmpbuf) + strlen(s) - 6); + strcpy(t, soap->tmpbuf + 6); + strcat(t, s + 1); + } + return t; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outstring(struct soap *soap, const char *tag, int id, char *const*p, const char *type, int n) +{ id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n); + if (id < 0 + || soap_element_begin_out(soap, tag, id, type) + || soap_string_out(soap, *p, 0) + || soap_element_end_out(soap, tag)) + return soap->error; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char ** +SOAP_FMAC2 +soap_instring(struct soap *soap, const char *tag, char **p, const char *type, int t, int flag, long minlen, long maxlen) +{ if (soap_element_begin_in(soap, tag, 1)) + { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG) + return NULL; + soap->error = SOAP_OK; + } + if (!p) + if (!(p = (char**)soap_malloc(soap, sizeof(char*)))) + return NULL; + if (soap->body) + { *p = soap_string_in(soap, flag, minlen, maxlen); + if (!*p || !(char*)soap_id_enter(soap, soap->id, *p, t, sizeof(char*), 0, NULL, NULL, NULL)) + return NULL; + } + else + *p = NULL; + if (*soap->href) + p = (char**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(char**), 0); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outwstring(struct soap *soap, const char *tag, int id, wchar_t *const*p, const char *type, int n) +{ id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n); + if (id < 0 + || soap_element_begin_out(soap, tag, id, type) + || soap_wstring_out(soap, *p, 0) + || soap_element_end_out(soap, tag)) + return soap->error; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +wchar_t ** +SOAP_FMAC2 +soap_inwstring(struct soap *soap, const char *tag, wchar_t **p, const char *type, int t, long minlen, long maxlen) +{ if (soap_element_begin_in(soap, tag, 1)) + { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG) + return NULL; + soap->error = SOAP_OK; + } + if (!p) + if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*)))) + return NULL; + if (soap->body) + { *p = soap_wstring_in(soap, 1, minlen, maxlen); + if (!*p || !(wchar_t*)soap_id_enter(soap, soap->id, *p, t, sizeof(wchar_t*), 0, NULL, NULL, NULL)) + return NULL; + } + else + *p = NULL; + if (*soap->href) + p = (wchar_t**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(wchar_t**), 0); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static time_t +soap_timegm(struct tm *T) +{ +#if defined(HAVE_TIMEGM) + return timegm(T); +#else + time_t t, g, z; +#ifdef HAVE_GMTIME_R + struct tm tm, *tmp = &tm; +#else + struct tm *tmp; +#endif + t = mktime(T); + if (t == -1) + return -1; +#ifdef HAVE_GMTIME_R + gmtime_r(&t, tmp); +#else + tmp = gmtime(&t); +#endif + tmp->tm_isdst = 0; + g = mktime(tmp); + if (g == -1) + return -1; + z = g - t; + return t - z; +#endif +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_dateTime2s(struct soap *soap, time_t n) +{ struct tm T, *pT = &T; +#if defined(HAVE_GMTIME_R) + if (gmtime_r(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); + /* The following defines were added for VxWorks*/ +#elif defined(HAVE_PGMTIME_R) + if (gmtime_r(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); +#elif defined(HAVE_PGMTIME) + if (gmtime(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); +#elif defined(HAVE_GMTIME) + if ((pT = gmtime(&n))) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); +#elif defined(HAVE_GETTIMEOFDAY) + struct timezone tz; + memset((void*)&tz, 0, sizeof(tz)); +# if defined(HAVE_LOCALTIME_R) + if (localtime_r(&n, pT)) + { struct timeval tv; + gettimeofday(&tv, &tz); + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60); + } +# else + if ((pT = localtime(&n))) + { struct timeval tv; + gettimeofday(&tv, &tz); + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60); + } +#endif +#elif defined(HAVE_FTIME) + struct timeb t; + memset((void*)&t, 0, sizeof(t)); +# if defined(HAVE_LOCALTIME_R) + if (localtime_r(&n, pT)) + { ftime(&t); + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60); + } + /* The following defines were added for VxWorks*/ +# elif defined(HAVE_PLOCALTIME_R) + if (localtime_r(&n, pT)) + { strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf+strlen(soap->tmpbuf), "%+03d:%02d", t.timezone/60, abs(t.timezone)%60); + } +# else + if ((pT = localtime(&n))) + { ftime(&t); + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60); + } +# endif +#elif defined(HAVE_LOCALTIME_R) + if (localtime_r(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + /* The following defines were added for VxWorks*/ +#elif defined(HAVE_PLOCALTIME_R) + if (localtime_r(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); +#else + if ((pT = localtime(&n))) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); +#endif + else + strcpy(soap->tmpbuf, "1969-12-31T23:59:59Z"); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outdateTime(struct soap *soap, const char *tag, int id, const time_t *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_dateTime2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2dateTime(struct soap *soap, const char *s, time_t *p) +{ if (s) + { struct tm T; + char zone[16]; + const char *t; + memset((void*)&T, 0, sizeof(T)); + zone[sizeof(zone)-1] = '\0'; + if (strchr(s, '-')) + t = "%d-%d-%dT%d:%d:%d%15s"; + else if (strchr(s, ':')) + t = "%4d%2d%2dT%d:%d:%d%15s"; + else /* parse non-XSD-standard alternative ISO 8601 format */ + t = "%4d%2d%2dT%2d%2d%2d%15s"; + sscanf(s, t, &T.tm_year, &T.tm_mon, &T.tm_mday, &T.tm_hour, &T.tm_min, &T.tm_sec, zone); + if (T.tm_year == 1) + T.tm_year = 70; + else + T.tm_year -= 1900; + T.tm_mon--; + if (*zone) + { if (*zone == '.') + { for (s = zone + 1; *s; s++) + if (*s < '0' || *s > '9') + break; + } + else + s = zone; + if (*s == '+' || *s == '-') + { int h = 0, m = 0; + if (s[3] == ':') + { sscanf(s, "%d:%d", &h, &m); + if (h < 0) + m = -m; + } + else + { m = (int)atol(s); + h = m / 100; + m = m % 100; + } + T.tm_hour -= h; + T.tm_min -= m; + } + *p = soap_timegm(&T); + } + else + *p = mktime(&T); /* no time zone: suppose it is localtime? */ + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +time_t * +SOAP_FMAC2 +soap_indateTime(struct soap *soap, const char *tag, time_t *p, const char * type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":dateTime")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } + p = (time_t*)soap_id_enter(soap, soap->id, p, t, sizeof(time_t), 0, NULL, NULL, NULL); + if (*soap->href) + p = (time_t*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(time_t), 0, NULL); + else if (p) + { if (soap_s2dateTime(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outliteral(struct soap *soap, const char *tag, char *const*p) +{ int i; + const char *t = NULL; + if (tag && *tag != '-') + { if (soap->local_namespaces && (t = strchr(tag, ':'))) + { strncpy(soap->tmpbuf, tag, t-tag); + soap->tmpbuf[t-tag] = '\0'; + for (i = 0; soap->local_namespaces[i].id; i++) + if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id)) + break; + t++; + sprintf(soap->tmpbuf, "<%s xmlns=\"%s\">", t, soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS); + } + else + { t = tag; + sprintf(soap->tmpbuf, "<%s>", tag); + } + if (soap_send(soap, soap->tmpbuf)) + return soap->error; + } + if (p && *p) + { if (soap_send(soap, *p)) + return soap->error; + } + if (t) + { sprintf(soap->tmpbuf, "", t); + return soap_send(soap, soap->tmpbuf); + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char ** +SOAP_FMAC2 +soap_inliteral(struct soap *soap, const char *tag, char **p) +{ if (soap_element_begin_in(soap, tag, 1)) + { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT) + return NULL; + soap->error = SOAP_OK; + } + if (!p) + if (!(p = (char**)soap_malloc(soap, sizeof(char*)))) + return NULL; + if (soap->null) + *p = NULL; + else + *p = soap_string_in(soap, 0, -1, -1); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outwliteral(struct soap *soap, const char *tag, wchar_t *const*p) +{ int i; + const char *t = NULL; + wchar_t c; + const wchar_t *s; + if (tag && *tag != '-') + { if (soap->local_namespaces && (t = strchr(tag, ':'))) + { strncpy(soap->tmpbuf, tag, t-tag); + soap->tmpbuf[t-tag] = '\0'; + for (i = 0; soap->local_namespaces[i].id; i++) + if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id)) + break; + t++; + sprintf(soap->tmpbuf, "<%s xmlns=\"%s\">", t, soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS); + } + else + { t = tag; + sprintf(soap->tmpbuf, "<%s>", tag); + } + if (soap_send(soap, soap->tmpbuf)) + return soap->error; + } + if (p) + { s = *p; + while ((c = *s++)) + if (soap_pututf8(soap, (unsigned char)c)) + return soap->error; + } + if (t) + { sprintf(soap->tmpbuf, "", t); + return soap_send(soap, soap->tmpbuf); + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +wchar_t ** +SOAP_FMAC2 +soap_inwliteral(struct soap *soap, const char *tag, wchar_t **p) +{ if (soap_element_begin_in(soap, tag, 1)) + { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT) + return NULL; + soap->error = SOAP_OK; + } + if (!p) + if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*)))) + return NULL; + if (soap->null) + *p = NULL; + else + *p = soap_wstring_in(soap, 0, -1, -1); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char * +SOAP_FMAC2 +soap_token(struct soap *soap) +{ register size_t i; + register soap_wchar c = 0; + register char *s = soap->tmpbuf; + if (!soap->body) + return SOAP_STR_EOS; + do c = soap_get(soap); + while (soap_blank(c)); + for (i = 0; i < sizeof(soap->tmpbuf) - 1; i++) + { if (c == SOAP_TT || (int)c == EOF || soap_blank(c)) + break; + *s++ = (char)c; + c = soap_get(soap); + } + if ((int)c == EOF || c == SOAP_TT) + soap_unget(soap, c); + *s = '\0'; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element content value='%s'\n", soap->tmpbuf)); + return soap->tmpbuf; /* return non-null pointer */ +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char * +SOAP_FMAC2 +soap_value(struct soap *soap) +{ register size_t i; + register soap_wchar c = 0; + register char *s = soap->tmpbuf; + if (!soap->body) + return SOAP_STR_EOS; + do c = soap_get(soap); + while (soap_blank(c)); + for (i = 0; i < sizeof(soap->tmpbuf) - 1; i++) + { if (c == SOAP_TT || (int)c == EOF) + break; + *s++ = (char)c; + c = soap_get(soap); + } + for (s--; i > 0; i--, s--) + if (!soap_blank(*s)) + break; + s[1] = '\0'; + if ((int)c == EOF || c == SOAP_TT) + soap_unget(soap, c); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element content value='%s'\n", soap->tmpbuf)); +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + soap->dom->data = soap_strdup(soap, soap->tmpbuf); +#endif + return soap->tmpbuf; /* return non-null pointer */ +} +#endif + +/******************************************************************************/ +#if !defined(WITH_LEANER) || !defined(WITH_NOHTTP) +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getline(struct soap *soap, char *s, int len) +{ int i = len; + soap_wchar c = 0; + for (;;) + { while (--i > 0) + { c = soap_getchar(soap); + if (c == '\r' || c == '\n') + break; + if ((int)c == EOF) + return soap->error = SOAP_EOF; + *s++ = (char)c; + } + if (c != '\n') + c = soap_getchar(soap); /* got \r, now get \n */ + if (c == '\n') + { *s = '\0'; + if (i+1 == len) /* empty line: end of HTTP/MIME header */ + break; + c = soap_unget(soap, soap_getchar(soap)); + if (c != ' ' && c != '\t') /* HTTP line continuation? */ + break; + } + else if ((int)c == EOF) + return soap->error = SOAP_EOF; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static size_t +soap_count_attachments(struct soap *soap) +{ +#ifndef WITH_LEANER + register struct soap_multipart *content; + register size_t count = soap->count; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the message size with attachments, current count=%lu\n", (unsigned long)count)); + if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of DIME attachments\n")); + for (content = soap->dime.first; content; content = content->next) + { count += 12 + ((content->size+3)&(~3)); + if (content->id) + count += ((strlen(content->id)+3)&(~3)); + if (content->type) + count += ((strlen(content->type)+3)&(~3)); + if (content->options) + count += ((((unsigned char)content->options[2] << 8) | ((unsigned char)content->options[3]))+7)&(~3); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of DIME attachment content is %lu bytes\n", (unsigned long)content->size)); + } + } + if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary) + { register size_t n = strlen(soap->mime.boundary); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of MIME attachments\n")); + for (content = soap->mime.first; content; content = content->next) + { register const char *s; + /* count \r\n--boundary\r\n */ + count += 6 + n; + /* count Content-Type: ...\r\n */ + if (content->type) + count += 16 + strlen(content->type); + /* count Content-Transfer-Encoding: ...\r\n */ + s = soap_str_code(mime_codes, content->encoding); + if (s) + count += 29 + strlen(s); + /* count Content-ID: ...\r\n */ + if (content->id) + count += 14 + strlen(content->id); + /* count Content-Location: ...\r\n */ + if (content->location) + count += 20 + strlen(content->location); + /* count Content-Description: ...\r\n */ + if (content->description) + count += 23 + strlen(content->location); + /* count \r\n...content */ + count += 2 + content->size; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of MIME attachment content is %lu bytes\n", (unsigned long)content->size)); + } + /* count \r\n--boundary-- */ + count += 6 + n; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New count is %lu bytes\n", (unsigned long)count)); + return count; +#else + return soap->count; +#endif +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static int +soap_putdimefield(struct soap *soap, const char *s, size_t n) +{ if (soap_send_raw(soap, s, n)) + return soap->error; + return soap_send_raw(soap, SOAP_STR_PADDING, -(long)n&3); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_dime_option(struct soap *soap, unsigned short optype, const char *option) +{ size_t n; + char *s = NULL; + if (option) + { n = strlen(option); + s = (char*)soap_malloc(soap, n + 5); + if (s) + { s[0] = optype >> 8; + s[1] = optype & 0xFF; + s[2] = n >> 8; + s[3] = n & 0xFF; + strcpy(s + 4, option); + } + } + return s; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putdimehdr(struct soap *soap) +{ unsigned char tmp[12]; + size_t optlen = 0, idlen = 0, typelen = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Put DIME header id='%s'\n", soap->dime.id?soap->dime.id:"")); + if (soap->dime.options) + optlen = (((unsigned char)soap->dime.options[2] << 8) | ((unsigned char)soap->dime.options[3])) + 4; + if (soap->dime.id) + idlen = strlen(soap->dime.id); + if (soap->dime.type) + typelen = strlen(soap->dime.type); + tmp[0] = SOAP_DIME_VERSION | (soap->dime.flags & 0x7); + tmp[1] = soap->dime.flags & 0xF0; + tmp[2] = optlen >> 8; + tmp[3] = optlen & 0xFF; + tmp[4] = idlen >> 8; + tmp[5] = idlen & 0xFF; + tmp[6] = typelen >> 8; + tmp[7] = typelen & 0xFF; + tmp[8] = soap->dime.size >> 24; + tmp[9] = (soap->dime.size >> 16) & 0xFF; + tmp[10] = (soap->dime.size >> 8) & 0xFF; + tmp[11] = soap->dime.size & 0xFF; + if (soap_send_raw(soap, (char*)tmp, 12) + || soap_putdimefield(soap, soap->dime.options, optlen) + || soap_putdimefield(soap, soap->dime.id, idlen) + || soap_putdimefield(soap, soap->dime.type, typelen)) + return soap->error; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putdime(struct soap *soap) +{ struct soap_multipart *content; + if (!(soap->mode & SOAP_ENC_DIME)) + return SOAP_OK; + for (content = soap->dime.first; content; content = content->next) + { void *handle; + soap->dime.size = content->size; + soap->dime.id = content->id; + soap->dime.type = content->type; + soap->dime.options = content->options; + soap->dime.flags = SOAP_DIME_VERSION | SOAP_DIME_MEDIA; + if (soap->fdimereadopen && ((handle = soap->fdimereadopen(soap, (void*)content->ptr, content->id, content->type, content->options)) || soap->error)) + { size_t size = content->size; + if (!handle) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadopen failed\n")); + return soap->error; + } + if (!content->size && ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE)) + { size_t chunksize = sizeof(soap->tmpbuf); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming DIME\n")); + do + { size = soap->fdimeread(soap, handle, soap->tmpbuf, chunksize); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread returned %lu bytes\n", (unsigned long)size)); + if (size < chunksize) + { soap->dime.flags &= ~SOAP_DIME_CF; + if (!content->next) + soap->dime.flags |= SOAP_DIME_ME; + } + else + soap->dime.flags |= SOAP_DIME_CF; + soap->dime.size = size; + if (soap_putdimehdr(soap) + || soap_putdimefield(soap, soap->tmpbuf, size)) + break; + if (soap->dime.id) + { soap->dime.flags &= ~(SOAP_DIME_MB | SOAP_DIME_MEDIA); + soap->dime.id = NULL; + soap->dime.type = NULL; + soap->dime.options = NULL; + } + } while (size >= chunksize); + } + else + { if (!content->next) + soap->dime.flags |= SOAP_DIME_ME; + if (soap_putdimehdr(soap)) + return soap->error; + do + { size_t bufsize; + if (size < sizeof(soap->tmpbuf)) + bufsize = size; + else + bufsize = sizeof(soap->tmpbuf); + if (!(bufsize = soap->fdimeread(soap, handle, soap->tmpbuf, bufsize))) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)soap->dime.size)); + soap->error = SOAP_EOF; + break; + } + if (soap_send_raw(soap, soap->tmpbuf, bufsize)) + break; + size -= bufsize; + } while (size); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n")); + soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3); + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n")); + if (soap->fdimereadclose) + soap->fdimereadclose(soap, handle); + } + else + { if (!content->next) + soap->dime.flags |= SOAP_DIME_ME; + if (soap_putdimehdr(soap) + || soap_putdimefield(soap, (char*)content->ptr, content->size)) + return soap->error; + } + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static char * +soap_getdimefield(struct soap *soap, size_t n) +{ register soap_wchar c; + register int i; + register char *s; + char *p = NULL; + if (n) + { p = (char*)soap_malloc(soap, n + 1); + if (p) + { s = p; + for (i = n; i > 0; i--) + { if ((int)(c = soap_get1(soap)) == EOF) + { soap->error = SOAP_EOF; + return NULL; + } + *s++ = (char)c; + } + *s = '\0'; + if ((soap->error = soap_move(soap, -(long)n&3))) + return NULL; + } + else + soap->error = SOAP_EOM; + } + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getdimehdr(struct soap *soap) +{ register soap_wchar c; + register char *s; + register int i; + unsigned char tmp[12]; + size_t optlen, idlen, typelen; + if (!(soap->mode & SOAP_ENC_DIME)) + return soap->error = SOAP_DIME_END; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME header\n")); + if (soap->dime.buflen || soap->dime.chunksize) + { if (soap_move(soap, (long)(soap->dime.size - soap_tell(soap)))) + return soap->error = SOAP_EOF; + soap_unget(soap, soap_getchar(soap)); /* skip padding and get hdr */ + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... From chunked\n")); + return SOAP_OK; + } + s = (char*)tmp; + for (i = 12; i > 0; i--) + { if ((int)(c = soap_getchar(soap)) == EOF) + return soap->error = SOAP_EOF; + *s++ = (char)c; + } + if ((tmp[0] & 0xF8) != SOAP_DIME_VERSION) + return soap->error = SOAP_DIME_MISMATCH; + soap->dime.flags = (tmp[0] & 0x7) | (tmp[1] & 0xF0); + optlen = (tmp[2] << 8) | tmp[3]; + idlen = (tmp[4] << 8) | tmp[5]; + typelen = (tmp[6] << 8) | tmp[7]; + soap->dime.size = (tmp[8] << 24) | (tmp[9] << 16) | (tmp[10] << 8) | tmp[11]; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME size=%lu flags=0x%X\n", (unsigned long)soap->dime.size, soap->dime.flags)); + if (!(soap->dime.options = soap_getdimefield(soap, optlen)) && soap->error) + return soap->error; + if (!(soap->dime.id = soap_getdimefield(soap, idlen)) && soap->error) + return soap->error; + if (!(soap->dime.type = soap_getdimefield(soap, typelen)) && soap->error) + return soap->error; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME id=%s, type=%s, options=%s\n", soap->dime.id?soap->dime.id:"", soap->dime.type?soap->dime.type:"", soap->dime.options?soap->dime.options+4:"")); + if (soap->dime.flags & SOAP_DIME_ME) + soap->mode &= ~SOAP_ENC_DIME; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getdime(struct soap *soap) +{ while (soap->dime.flags & SOAP_DIME_CF) + { if (soap_getdimehdr(soap)) + return soap->error; + if (soap_move(soap, soap->dime.size)) + return soap->error = SOAP_EOF; + } + if (soap_move(soap, ((soap->dime.size+3)&(~3))-soap_tell(soap))) + return soap->error = SOAP_EOF; + for (;;) + { register struct soap_multipart *content; + if (soap_getdimehdr(soap)) + break; + if (soap->fdimewriteopen && ((soap->dime.ptr = (char*)soap->fdimewriteopen(soap, soap->dime.id, soap->dime.type, soap->dime.options)) || soap->error)) + { const char *id, *type, *options; + size_t size, n; + if (!soap->dime.ptr) + return soap->error; + id = soap->dime.id; + type = soap->dime.type; + options = soap->dime.options; + for (;;) + { size = soap->dime.size; + for (;;) + { n = soap->buflen - soap->bufidx; + if (size < n) + n = size; + if ((soap->error = soap->fdimewrite(soap, (void*)soap->dime.ptr, soap->buf + soap->bufidx, n))) + break; + size -= n; + if (!size) + { soap->bufidx += n; + break; + } + if (soap_recv(soap)) + { soap->error = SOAP_EOF; + goto end; + } + } + if (soap_move(soap, -(long)soap->dime.size&3)) + { soap->error = SOAP_EOF; + break; + } + if (!(soap->dime.flags & SOAP_DIME_CF)) + break; + if (soap_getdimehdr(soap)) + break; + } +end: + if (soap->fdimewriteclose) + soap->fdimewriteclose(soap, (void*)soap->dime.ptr); + soap->dime.size = 0; + soap->dime.id = id; + soap->dime.type = type; + soap->dime.options = options; + } + else if (soap->dime.flags & SOAP_DIME_CF) + { const char *id, *type, *options; + register soap_wchar c; + register char *s; + register int i; + id = soap->dime.id; + type = soap->dime.type; + options = soap->dime.options; + if (soap_new_block(soap)) + return SOAP_EOM; + for (;;) + { s = (char*)soap_push_block(soap, soap->dime.size); + if (!s) + return soap->error = SOAP_EOM; + for (i = soap->dime.size; i > 0; i--) + { if ((int)(c = soap_get1(soap)) == EOF) + return soap->error = SOAP_EOF; + *s++ = (char)c; + } + if (soap_move(soap, -(long)soap->dime.size&3)) + return soap->error = SOAP_EOF; + if (!(soap->dime.flags & SOAP_DIME_CF)) + break; + if (soap_getdimehdr(soap)) + return soap->error; + } + soap->dime.size = soap->blist->size++; /* allocate one more for '\0' */ + if (!(soap->dime.ptr = soap_save_block(soap, NULL, 0))) + return soap->error; + soap->dime.ptr[soap->dime.size] = '\0'; /* force 0-terminated */ + soap->dime.id = id; + soap->dime.type = type; + soap->dime.options = options; + } + else + soap->dime.ptr = soap_getdimefield(soap, soap->dime.size); + content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, soap->dime.ptr, soap->dime.size); + if (!content) + return soap->error = SOAP_EOM; + content->id = soap->dime.id; + content->type = soap->dime.type; + content->options = soap->dime.options; + soap_resolve_attachment(soap, content); + if (soap->error) + return soap->error; + } + if (soap->error != SOAP_DIME_END) + return soap->error; + return soap->error = SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getmimehdr(struct soap *soap) +{ struct soap_multipart *content; + do + { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) + return soap->error; + } + while (!*soap->msgbuf); + if (soap->msgbuf[0] == '-' && soap->msgbuf[1] == '-') + { char *s = soap->msgbuf + strlen(soap->msgbuf) - 1; + /* remove white space */ + while (soap_blank(*s)) + s--; + s[1] = '\0'; + if (soap->mime.boundary) + { if (strcmp(soap->msgbuf + 2, soap->mime.boundary)) + return soap->error = SOAP_MIME_ERROR; + } + else + soap->mime.boundary = soap_strdup(soap, soap->msgbuf + 2); + if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) + return soap->error; + } + if (soap_set_mime_attachment(soap, NULL, 0, SOAP_MIME_NONE, NULL, NULL, NULL, NULL)) + return soap->error = SOAP_EOM; + content = soap->mime.last; + for (;;) + { register char *key = soap->msgbuf; + register char *val; + if (!*key) + break; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "MIME header: %s\n", key)); + val = strchr(soap->msgbuf, ':'); + if (val) + { *val = '\0'; + do val++; + while (*val && *val <= 32); + if (!soap_tag_cmp(key, "Content-ID")) + content->id = soap_strdup(soap, val); + else if (!soap_tag_cmp(key, "Content-Location")) + content->location = soap_strdup(soap, val); + else if (!soap_tag_cmp(key, "Content-Disposition")) + content->id = soap_strdup(soap, soap_get_header_attribute(soap, val, "name")); + else if (!soap_tag_cmp(key, "Content-Type")) + content->type = soap_strdup(soap, val); + else if (!soap_tag_cmp(key, "Content-Description")) + content->description = soap_strdup(soap, val); + else if (!soap_tag_cmp(key, "Content-Transfer-Encoding")) + content->encoding = (enum soap_mime_encoding)soap_int_code(mime_codes, val, (long)SOAP_MIME_NONE); + } + if (soap_getline(soap, key, sizeof(soap->msgbuf))) + return soap->error; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getmime(struct soap *soap) +{ register soap_wchar c = 0; + if (!soap->mime.last) + return SOAP_OK; + for (;;) + { register size_t i, m = 0; + register char *s, *t = NULL; + struct soap_multipart *content = soap->mime.last; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Parsing MIME content id=%s type=%s\n", content->id?content->id:"", content->type?content->type:"")); + if (soap_new_block(soap)) + return soap->error = SOAP_EOM; + for (;;) + { register short flag = 0; + if (!(s = (char*)soap_push_block(soap, SOAP_BLKLEN))) + return soap->error = SOAP_EOM; + for (i = 0; i < SOAP_BLKLEN; i++) + { if (m > 0) + { flag = (*t == '\r'); + *s++ = *t++; + m--; + } + else + { if (!flag) + { c = soap_get1(soap); + if ((int)c == EOF) + return soap->error = SOAP_EOF; + } + if (flag || c == '\r') + { t = soap->tmpbuf; + memset(t, 0, sizeof(soap->tmpbuf)); + strcpy(t, "\n--"); + if (soap->mime.boundary) + strncat(t, soap->mime.boundary, sizeof(soap->tmpbuf)-4); + do c = soap_getchar(soap); + while (c == *t++); + if ((int)c == EOF) + return soap->error = SOAP_EOF; + if (!*--t) + goto end; + *t = (char)c; + m = t - soap->tmpbuf + 1; + t = soap->tmpbuf; + c = '\r'; + } + *s++ = (char)c; + } + } + } +end: + *s = '\0'; /* force 0-terminated */ + content->size = soap_size_block(soap, i+1)-1; + content->ptr = soap_save_block(soap, NULL, 0); + soap_resolve_attachment(soap, content); + if (c == '-' && soap_getchar(soap) == '-') + break; + while (c != '\r' && (int)c != EOF && soap_blank(c)) + c = soap_getchar(soap); + if (c != '\r' || soap_getchar(soap) != '\n') + return soap->error = SOAP_MIME_ERROR; + if (soap_getmimehdr(soap)) + return soap->error; + } + /* + do c = soap_getchar(soap); + while ((int)c != EOF && c != '\r' && c != '\n'); + if ((int)c != '\r' || soap_getchar(soap) != '\n') + return soap->error = SOAP_MIME_ERROR; + */ + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static int +soap_match_cid(const char *s, const char *t) +{ register size_t n; + if (!s) + return 1; + if (!strcmp(s, t)) + return 0; + if (!strncmp(s, "cid:", 4)) + s += 4; + n = strlen(t); + if (*t == '<') + { t++; + n -= 2; + } + if (!strncmp(s, t, n) && !s[n]) + return 0; + return 1; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static void +soap_resolve_attachment(struct soap *soap, struct soap_multipart *content) +{ if (content->id) + { register struct soap_xlist **xp = &soap->xlist; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving attachment data for id=%s\n", content->id)); + while (*xp) + { register struct soap_xlist *xq = *xp; + if (!soap_match_cid(xq->id, content->id)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Found matching attachment %s for content id=%s\n", xq->id, content->id)); + *xp = xq->next; + *xq->ptr = (unsigned char*)content->ptr; + *xq->size = (int)content->size; + *xq->type = (char*)content->type; + if (content->options) + *xq->options = (char*)content->options; + else + *xq->options = (char*)content->description; + SOAP_FREE(soap, xq); + } + else + xp = &(*xp)->next; + } + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putmimehdr(struct soap *soap, struct soap_multipart *content) +{ const char *s; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "MIME attachment type=%s\n", content->type?content->type:"")); + if (soap_send3(soap, "\r\n--", soap->mime.boundary, "\r\n")) + return soap->error; + if (content->type && soap_send3(soap, "Content-Type: ", content->type, "\r\n")) + return soap->error; + s = soap_str_code(mime_codes, content->encoding); + if (s && soap_send3(soap, "Content-Transfer-Encoding: ", s, "\r\n")) + return soap->error; + if (content->id && soap_send3(soap, "Content-ID: ", content->id, "\r\n")) + return soap->error; + if (content->location && soap_send3(soap, "Content-Location: ", content->location, "\r\n")) + return soap->error; + if (content->description && soap_send3(soap, "Content-Description: ", content->description, "\r\n")) + return soap->error; + return soap_send_raw(soap, "\r\n", 2); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putmime(struct soap *soap) +{ struct soap_multipart *content; + if (!(soap->mode & SOAP_ENC_MIME) || !soap->mime.boundary) + return SOAP_OK; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending MIME attachments\n")); + for (content = soap->mime.first; content; content = content->next) + if (soap_putmimehdr(soap, content) + || soap_send_raw(soap, content->ptr, content->size)) + return soap->error; + return soap_send3(soap, "\r\n--", soap->mime.boundary, "--"); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_dime(struct soap *soap) +{ soap->omode |= SOAP_ENC_DIME; + soap->dime.first = NULL; + soap->dime.last = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_mime(struct soap *soap, const char *boundary, const char *start) +{ soap->omode |= SOAP_ENC_MIME; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = soap_strdup(soap, boundary); + soap->mime.start = soap_strdup(soap, start); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_clr_dime(struct soap *soap) +{ soap->omode &= ~SOAP_ENC_DIME; + soap->dime.first = NULL; + soap->dime.last = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_clr_mime(struct soap *soap) +{ soap->omode &= ~SOAP_ENC_MIME; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = NULL; + soap->mime.start = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static struct soap_multipart* +soap_new_multipart(struct soap *soap, struct soap_multipart **first, struct soap_multipart **last, char *ptr, size_t size) +{ struct soap_multipart *content; + content = (struct soap_multipart*)soap_malloc(soap, sizeof(struct soap_multipart)); + if (content) + { content->next = NULL; + content->ptr = ptr; + content->size = size; + content->id = NULL; + content->type = NULL; + content->options = NULL; + content->encoding = SOAP_MIME_NONE; + content->location = NULL; + content->description = NULL; + if (!*first) + *first = content; + if (*last) + (*last)->next = content; + *last = content; + } + return content; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_dime_attachment(struct soap *soap, char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option) +{ struct soap_multipart *content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, ptr, size); + if (!content) + return SOAP_EOM; + content->id = soap_strdup(soap, id); + content->type = soap_strdup(soap, type); + content->options = soap_dime_option(soap, optype, option); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_mime_attachment(struct soap *soap, char *ptr, size_t size, enum soap_mime_encoding encoding, const char *type, const char *id, const char *location, const char *description) +{ struct soap_multipart *content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, ptr, size); + if (!content) + return SOAP_EOM; + content->id = soap_strdup(soap, id); + content->type = soap_strdup(soap, type); + content->encoding = encoding; + content->location = soap_strdup(soap, location); + content->description = soap_strdup(soap, description); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +struct soap_multipart* +SOAP_FMAC2 +soap_next_multipart(struct soap_multipart *content) +{ if (content) + return content->next; + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static void +soap_select_mime_boundary(struct soap *soap) +{ while (!soap->mime.boundary || soap_valid_mime_boundary(soap)) + { register char *s = soap->mime.boundary; + register size_t n = 0; + if (s) + n = strlen(s); + if (n < 16) + { n = 72; + s = soap->mime.boundary = (char*)soap_malloc(soap, n + 1); + if (!s) + return; + } + strcpy(s, "<>"); + s += 2; + n -= 4; + while (n) + { *s++ = soap_base64o[soap_random & 0x3F]; + n--; + } + strcpy(s, "<>"); + } + if (!soap->mime.start) + soap->mime.start = ""; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static int +soap_valid_mime_boundary(struct soap *soap) +{ register struct soap_multipart *content; + register size_t k = strlen(soap->mime.boundary); + for (content = soap->mime.first; content; content = content->next) + { if (content->ptr && content->size >= k) + { register const char *p = (const char*)content->ptr; + register size_t i; + for (i = 0; i < content->size - k; i++, p++) + if (!strncmp(p, soap->mime.boundary, k)) + return SOAP_ERR; + } + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ + +#ifdef WITH_COOKIES +/******************************************************************************/ +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_encode_cookie(const char *s, char *t, size_t len) +{ register int c; + register size_t n = len; + while ((c = *s++) && --n > 0) + { if (c > ' ' && c < 128 && !strchr("()<>@,;:\\\"/[]?={}", c)) + *t++ = c; + else if (n > 2) + { *t++ = '%'; + *t++ = (c >> 4) + (c > 159 ? '7' : '0'); + c &= 0xF; + *t++ = c + (c > 9 ? '7' : '0'); + n -= 2; + } + else + break; + } + *t = '\0'; + return len - n; +} + +/******************************************************************************/ +SOAP_FMAC1 +struct soap_cookie* +SOAP_FMAC2 +soap_cookie(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + size_t n; + if (!domain) + domain = soap->cookie_domain; + if (!path) + path = soap->cookie_path; + if (*path == '/') + path++; + n = strlen(path); + for (p = soap->cookies; p; p = p->next) + if (!strcmp(p->name, name) + && domain + && p->domain + && !strcmp(p->domain, domain) + && !strncmp(p->path, path, n)) + break; + return p; +} + +/******************************************************************************/ +SOAP_FMAC1 +struct soap_cookie* +SOAP_FMAC2 +soap_set_cookie(struct soap *soap, const char *name, const char *value, const char *domain, const char *path) +{ struct soap_cookie **p, *q; + int n; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set cookie: %s=%s domain=%s path=%s\n", name, value?value:"", domain?domain:"", path?path:"")); + if (!domain) + domain = soap->cookie_domain; + if (!path) + path = soap->cookie_path; + if (!path) + { soap_set_receiver_error(soap, "Cookie path not set", NULL, SOAP_HTTP_ERROR); + return NULL; + } + if (*path == '/') + path++; + q = soap_cookie(soap, name, domain, path); + if (!q) + { if ((q = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie)))) + { if ((q->name = (char*)SOAP_MALLOC(soap, strlen(name)+1))) + strcpy(q->name, name); + q->value = NULL; + q->domain = NULL; + q->path = NULL; + q->expire = -1; + q->version = 0; + q->secure = 0; + q->modified = 0; + for (p = &soap->cookies, n = soap->cookie_max; *p && n; p = &(*p)->next, n--) + if (!strcmp((*p)->name, name) && (*p)->path && strcmp((*p)->path, path) < 0) + break; + if (n) + { q->next = *p; + *p = q; + } + else + { SOAP_FREE(soap, q->name); + SOAP_FREE(soap, q); + q = NULL; + } + } + } + else + q->modified = 1; + if (q) + { if (q->value) + { SOAP_FREE(soap, q->value); + q->value = NULL; + } + if (q->domain) + { SOAP_FREE(soap, q->domain); + q->domain = NULL; + } + if (q->path) + { SOAP_FREE(soap, q->path); + q->path = NULL; + } + if (value && *value && (q->value = (char*)SOAP_MALLOC(soap, strlen(value)+1))) + strcpy(q->value, value); + if (domain && *domain && (q->domain = (char*)SOAP_MALLOC(soap, strlen(domain)+1))) + strcpy(q->domain, domain); + if (path && *path && (q->path = (char*)SOAP_MALLOC(soap, strlen(path)+1))) + strcpy(q->path, path); + q->session = 1; + q->env = 0; + } + return q; +} + +/******************************************************************************/ +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_clr_cookie(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie **p, *q; + if (!domain) + domain = soap->cookie_domain; + if (!domain) + { soap_set_receiver_error(soap, "Cookie domain not set", NULL, SOAP_HTTP_ERROR); + return; + } + if (!path) + path = soap->cookie_path; + if (!path) + { soap_set_receiver_error(soap, "Cookie path not set", NULL, SOAP_HTTP_ERROR); + return; + } + if (*path == '/') + path++; + for (p = &soap->cookies, q = *p; q; q = *p) + if (!strcmp(q->name, name) && !strcmp(q->domain, domain) && !strncmp(q->path, path, strlen(q->path))) + { if (q->value) + SOAP_FREE(soap, q->value); + if (q->domain) + SOAP_FREE(soap, q->domain); + if (q->path) + SOAP_FREE(soap, q->path); + *p = q->next; + SOAP_FREE(soap, q); + } + else + p = &q->next; +} + +/******************************************************************************/ +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + return p->value; + return NULL; +} + +/******************************************************************************/ +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_env_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path)) && p->env) + return p->value; + return NULL; +} + +/******************************************************************************/ +SOAP_FMAC1 +long +SOAP_FMAC2 +soap_cookie_expire(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + return p->expire; + return -1; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_cookie_expire(struct soap *soap, const char *name, long expire, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + { p->expire = expire; + p->modified = 1; + return SOAP_OK; + } + return SOAP_ERR; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + { p->session = 1; + p->modified = 1; + return SOAP_OK; + } + return SOAP_ERR; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_clr_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + { p->session = 0; + p->modified = 1; + return SOAP_OK; + } + return SOAP_ERR; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putsetcookies(struct soap *soap) +{ struct soap_cookie *p; + char *s, tmp[4096]; + const char *t; + for (p = soap->cookies; p; p = p->next) + { if (p->modified || !p->env) + { s = tmp; + if (p->name) + s += soap_encode_cookie(p->name, s, tmp-s+4064); + if (p->value && *p->value) + { *s++ = '='; + s += soap_encode_cookie(p->value, s, tmp-s+4064); + } + if (p->domain && (int)strlen(p->domain) < tmp-s+4064) + sprintf(s, ";Domain=\"%s\"", p->domain); + else if (soap->cookie_domain && (int)strlen(soap->cookie_domain) < tmp-s+4064) + sprintf(s, ";Domain=\"%s\"", soap->cookie_domain); + strcat(s, ";Path=\"/"); + if (p->path) + t = p->path; + else + t = soap->cookie_path; + if (t) + { if (*t == '/') + t++; + if ((int)strlen(t) < tmp-s+4064) + strcat(s, t); + } + s += strlen(s); + *s++ = '"'; + if (p->version > 0) + sprintf(s, ";Version=%u", p->version); + if (p->expire >= 0) + sprintf(s, ";Max-Age=%ld", p->expire); + if (p->secure) + strcat(s, ";Secure"); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set-Cookie: %s\n", tmp)); + if ((soap->error = soap->fposthdr(soap, "Set-Cookie", tmp))) + return soap->error; + } + } + return SOAP_OK; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putcookies(struct soap *soap, const char *domain, const char *path, int secure) +{ struct soap_cookie **p, *q; + unsigned int version = 0; + time_t now = time(NULL); + char *s, tmp[4096]; + p = &soap->cookies; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending cookies for domain=%s path=%s\n", domain, path)); + if (*path == '/') + path++; + while ((q = *p)) + { if (q->expire && now > q->expire) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie %s expired\n", q->name)); + SOAP_FREE(soap, q->name); + if (q->value) + SOAP_FREE(soap, q->value); + if (q->domain) + SOAP_FREE(soap, q->domain); + if (q->path) + SOAP_FREE(soap, q->path); + *p = q->next; + SOAP_FREE(soap, q); + } + else + { size_t domlen = 0; + if (q->domain) + { const char *s = strchr(q->domain, ':'); + if (s) + domlen = s - q->domain; + else + domlen = strlen(q->domain); + } + if ((!q->domain || !strncmp(q->domain, domain, domlen)) + && (!q->path || !strncmp(q->path, path, strlen(q->path))) + && (!q->secure || secure)) + { s = tmp; + if (q->version != version) + { sprintf(s, "$Version=%u;", q->version); + version = q->version; + } + if (q->name) + s += soap_encode_cookie(q->name, s, tmp-s+4080); + if (q->value && *q->value) + { *s++ = '='; + s += soap_encode_cookie(q->value, s, tmp-s+4080); + } + if (q->path && (int)strlen(q->path) < tmp-s+4080) + { sprintf(s, ";$Path=\"/%s\"", (*q->path == '/' ? q->path + 1 : q->path)); + s += strlen(s); + } + if (q->domain && (int)strlen(q->domain) < tmp-s+4080) + sprintf(s, ";$Domain=\"%s\"", q->domain); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie: %s\n", tmp)); + if ((soap->error = soap->fposthdr(soap, "Cookie", tmp))) + return soap->error; + } + p = &q->next; + } + } + return SOAP_OK; +} + +/******************************************************************************/ +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_getcookies(struct soap *soap, const char *val) +{ struct soap_cookie *p = NULL, *q; + const char *s; + char *t, tmp[4096]; /* cookie size is up to 4096 bytes [RFC2109] */ + char *domain = NULL; + char *path = NULL; + unsigned int version = 0; + time_t now = time(NULL); + if (!val) + return; + s = val; + while (*s) + { s = soap_decode_key(tmp, sizeof(tmp), s); + if (!soap_tag_cmp(tmp, "$Version")) + { if ((s = soap_decode_val(tmp, sizeof(tmp), s))) + { if (p) + p->version = (int)atol(tmp); + else + version = (int)atol(tmp); + } + } + else if (!soap_tag_cmp(tmp, "$Path")) + { s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) + strcpy(t, tmp); + } + else + t = NULL; + if (p) + { if (p->path) + SOAP_FREE(soap, p->path); + p->path = t; + } + else + { if (path) + SOAP_FREE(soap, path); + path = t; + } + } + else if (!soap_tag_cmp(tmp, "$Domain")) + { s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) + strcpy(t, tmp); + } + else + t = NULL; + if (p) + { if (p->domain) + SOAP_FREE(soap, p->domain); + p->domain = t; + } + else + { if (domain) + SOAP_FREE(soap, domain); + domain = t; + } + } + else if (p && !soap_tag_cmp(tmp, "Path")) + { if (p->path) + SOAP_FREE(soap, p->path); + s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { if ((p->path = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) + strcpy(p->path, tmp); + } + else + p->path = NULL; + } + else if (p && !soap_tag_cmp(tmp, "Domain")) + { if (p->domain) + SOAP_FREE(soap, p->domain); + s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { if ((p->domain = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) + strcpy(p->domain, tmp); + } + else + p->domain = NULL; + } + else if (p && !soap_tag_cmp(tmp, "Version")) + { s = soap_decode_val(tmp, sizeof(tmp), s); + p->version = (unsigned int)atol(tmp); + } + else if (p && !soap_tag_cmp(tmp, "Max-Age")) + { s = soap_decode_val(tmp, sizeof(tmp), s); + p->expire = now + atol(tmp); + } + else if (p && !soap_tag_cmp(tmp, "Expires")) + { struct tm T; + char a[3]; + static const char mns[] = "anebarprayunulugepctovec"; + s = soap_decode_val(tmp, sizeof(tmp), s); + if (strlen(tmp) > 20) + { memset((void*)&T, 0, sizeof(T)); + a[0] = tmp[4]; + a[1] = tmp[5]; + a[2] = '\0'; + T.tm_mday = (int)atol(a); + a[0] = tmp[8]; + a[1] = tmp[9]; + T.tm_mon = (strstr(mns, a) - mns) / 2; + a[0] = tmp[11]; + a[1] = tmp[12]; + T.tm_year = 100 + (int)atol(a); + a[0] = tmp[13]; + a[1] = tmp[14]; + T.tm_hour = (int)atol(a); + a[0] = tmp[16]; + a[1] = tmp[17]; + T.tm_min = (int)atol(a); + a[0] = tmp[19]; + a[1] = tmp[20]; + T.tm_sec = (int)atol(a); + p->expire = soap_timegm(&T); + } + } + else if (p && !soap_tag_cmp(tmp, "Secure")) + p->secure = 1; + else + { if (p) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie %s=%s domain=%s path=%s expire=%ld secure=%d\n", p->name, p->value?p->value:"", p->domain?p->domain:"", p->path?p->path:"", p->expire, p->secure)); + if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path))) + { q->version = p->version; + q->expire = p->expire; + q->secure = p->secure; + q->env = 1; + } + if (p->name) + SOAP_FREE(soap, p->name); + if (p->value) + SOAP_FREE(soap, p->value); + if (p->domain) + SOAP_FREE(soap, p->domain); + if (p->path) + SOAP_FREE(soap, p->path); + SOAP_FREE(soap, p); + } + if ((p = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie)))) + { p->name = (char*)SOAP_MALLOC(soap, strlen(tmp)+1); + strcpy(p->name, tmp); + s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { p->value = (char*)SOAP_MALLOC(soap, strlen(tmp)+1); + strcpy(p->value, tmp); + } + else + p->value = NULL; + p->domain = domain; + p->path = path; + p->expire = 0; + p->secure = 0; + p->version = version; + } + } + } + if (p) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie %s=%s domain=%s path=%s expire=%ld secure=%d\n", p->name, p->value?p->value:"", p->domain?p->domain:"", p->path?p->path:"", p->expire, p->secure)); + if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path))) + { q->version = p->version; + q->expire = p->expire; + q->secure = p->secure; + q->env = 1; + } + if (p->name) + SOAP_FREE(soap, p->name); + if (p->value) + SOAP_FREE(soap, p->value); + if (p->domain) + SOAP_FREE(soap, p->domain); + if (p->path) + SOAP_FREE(soap, p->path); + SOAP_FREE(soap, p); + } + if (domain) + SOAP_FREE(soap, domain); + if (path) + SOAP_FREE(soap, path); +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getenv_cookies(struct soap *soap) +{ struct soap_cookie *p; + const char *s; + char key[4096], val[4096]; /* cookie size is up to 4096 bytes [RFC2109] */ + if (!(s = getenv("HTTP_COOKIE"))) + return SOAP_ERR; + do + { s = soap_decode_key(key, sizeof(key), s); + s = soap_decode_val(val, sizeof(val), s); + p = soap_set_cookie(soap, key, val, NULL, NULL); + if (p) + p->env = 1; + } while (*s); + return SOAP_OK; +} + +/******************************************************************************/ +SOAP_FMAC1 +struct soap_cookie* +SOAP_FMAC2 +soap_copy_cookies(struct soap *soap) +{ struct soap_cookie *p, **q, *r; + q = &r; + for (p = soap->cookies; p; p = p->next) + { if (!(*q = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie)))) + return r; + **q = *p; + if (p->name) + { if (((*q)->name = (char*)SOAP_MALLOC(soap, strlen(p->name)+1))) + strcpy((*q)->name, p->name); + } + if (p->value) + { if (((*q)->value = (char*)SOAP_MALLOC(soap, strlen(p->value)+1))) + strcpy((*q)->value, p->value); + } + if (p->domain) + { if (((*q)->domain = (char*)SOAP_MALLOC(soap, strlen(p->domain)+1))) + strcpy((*q)->domain, p->domain); + } + if (p->path) + { if (((*q)->path = (char*)SOAP_MALLOC(soap, strlen(p->path)+1))) + strcpy((*q)->path, p->path); + } + q = &(*q)->next; + } + *q = NULL; + return r; +} + +/******************************************************************************/ +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_free_cookies(struct soap *soap) +{ struct soap_cookie *p; + for (p = soap->cookies; p; p = soap->cookies) + { soap->cookies = p->next; + SOAP_FREE(soap, p->name); + if (p->value) + SOAP_FREE(soap, p->value); + if (p->domain) + SOAP_FREE(soap, p->domain); + if (p->path) + SOAP_FREE(soap, p->path); + SOAP_FREE(soap, p); + } +} + +/******************************************************************************/ +#endif /* WITH_COOKIES */ + +/******************************************************************************/ +#ifdef WITH_GZIP +#ifndef PALM_1 +static int +soap_getgziphdr(struct soap *soap) +{ int i; + soap_wchar c, f = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get gzip header\n")); + for (i = 0; i < 9; i++) + { if ((int)(c = soap_get1(soap) == EOF)) + return soap->error = SOAP_EOF; + if (i == 2) + f = c; + } + if (f & 0x04) /* FEXTRA */ + { for (i = soap_get1(soap) | (soap_get1(soap) << 8); i; i--) + if ((int)soap_get1(soap) == EOF) + return soap->error = SOAP_EOF; + } + if (f & 0x08) /* FNAME */ + do + c = soap_get1(soap); + while (c && (int)c != EOF); + if ((int)c != EOF && (f & 0x10)) /* FCOMMENT */ + do + c = soap_get1(soap); + while (c && (int)f != EOF); + if ((int)c != EOF && (f & 0x01)) /* FHCRC */ + { if ((int)(c = soap_get1(soap)) != EOF) + c = soap_get1(soap); + } + if ((int)c == EOF) + return soap->error = SOAP_EOF; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_begin_recv(struct soap *soap) +{ soap_wchar c; + soap->error = SOAP_OK; + soap_free(soap); + soap_set_local_namespaces(soap); + soap->version = 0; /* don't assume we're parsing SOAP content by default */ +#ifndef WITH_NOIDREF + soap_free_iht(soap); +#endif + if ((soap->imode & SOAP_IO) == SOAP_IO_CHUNK) + soap->omode |= SOAP_IO_CHUNK; + soap->imode &= ~SOAP_IO; + soap->mode = soap->imode; + if (!soap->keep_alive) + { soap->buflen = 0; + soap->bufidx = 0; + } + if (!(soap->mode & SOAP_IO_KEEPALIVE)) + soap->keep_alive = 0; + soap->ahead = 0; + soap->peeked = 0; + soap->level = 0; + soap->part = SOAP_BEGIN; + soap->alloced = 0; + soap->count = 0; + soap->length = 0; + soap->cdata = 0; + *soap->endpoint = '\0'; + soap->action = NULL; +#ifndef WITH_LEANER + soap->dom = NULL; + soap->dime.chunksize = 0; + soap->dime.buflen = 0; + soap->dime.list = NULL; + soap->dime.first = NULL; + soap->dime.last = NULL; + soap->mime.list = NULL; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = NULL; + soap->mime.start = NULL; + soap->xlist = NULL; +#endif +#ifdef WIN32 +#ifndef UNDER_CE +#ifndef WITH_FASTCGI + if (!soap_valid_socket(soap->socket)) +#ifdef __BORLANDC__ + setmode((SOAP_SOCKET)soap->recvfd, O_BINARY); +#else + _setmode((SOAP_SOCKET)soap->recvfd, _O_BINARY); +#endif +#endif +#endif +#endif +#ifdef WITH_ZLIB + soap->mode &= ~SOAP_ENC_ZLIB; + soap->zlib_in = SOAP_ZLIB_NONE; + soap->zlib_out = SOAP_ZLIB_NONE; + soap->d_stream.next_in = Z_NULL; + soap->d_stream.avail_in = 0; + soap->d_stream.next_out = (Byte*)soap->buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + soap->z_ratio_in = 1.0; +#endif +#ifndef WITH_LEANER + if (soap->fprepareinit) + soap->fprepareinit(soap); +#endif + c = soap_getchar(soap); +#ifdef WITH_GZIP + if (c == 0x1F) + { if (soap_getgziphdr(soap)) + return soap->error; + if (inflateInit2(&soap->d_stream, -MAX_WBITS) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; + soap->zlib_state = SOAP_ZLIB_INFLATE; + soap->mode |= SOAP_ENC_ZLIB; + soap->zlib_in = SOAP_ZLIB_GZIP; + soap->z_crc = crc32(0L, NULL, 0); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n")); + memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); + /* should not chunk over plain transport, so why bother to check? */ + /* if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) */ + /* soap->z_buflen = soap->bufidx; */ + /* else */ + soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx); + soap->d_stream.avail_in = soap->buflen - soap->bufidx; + soap->z_buflen = soap->buflen; + soap->buflen = soap->bufidx; + c = soap_getchar(soap); + } +#endif +#ifndef WITH_LEANER + if (c == '-' && soap_get0(soap) == '-') + soap->mode |= SOAP_ENC_MIME; + else if ((c & 0xFFFC) == (SOAP_DIME_VERSION | SOAP_DIME_MB) && (soap_get0(soap) & 0xFFF0) == 0x20) + soap->mode |= SOAP_ENC_DIME; + else +#endif + { while (soap_blank(c)) + c = soap_getchar(soap); + } + if ((int)c == EOF) + return soap->error = SOAP_EOF; + soap_unget(soap, c); +#ifndef WITH_NOHTTP + /* if not XML or (start of)BOM or MIME/DIME/ZLIB, assume HTTP header */ + if (c != '<' && c != 0xEF && !(soap->mode & (SOAP_ENC_MIME | SOAP_ENC_DIME | SOAP_ENC_ZLIB))) + { soap->mode &= ~SOAP_IO; + soap->error = soap->fparse(soap); + if (soap->error && soap->error < SOAP_STOP) + { soap->keep_alive = 0; /* force close later */ + return soap->error; + } + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) + { soap->chunkbuflen = soap->buflen; + soap->buflen = soap->bufidx; + soap->chunksize = 0; + } +#ifndef WITH_LEANER + else if (soap->fpreparerecv && soap->buflen != soap->bufidx) + soap->fpreparerecv(soap, soap->buf + soap->bufidx, soap->buflen - soap->bufidx); +#endif +#ifdef WITH_ZLIB + if (soap->zlib_in != SOAP_ZLIB_NONE) + { /* fparse should not use soap_unget to push back last char */ +#ifdef WITH_GZIP + c = soap_get1(soap); + if (c == 0x1F) + { if (soap_getgziphdr(soap)) + return soap->error; + if (inflateInit2(&soap->d_stream, -MAX_WBITS) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; + soap->zlib_state = SOAP_ZLIB_INFLATE; + soap->z_crc = crc32(0L, NULL, 0); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n")); + } + else + { soap_revget1(soap); +#else + { +#endif + if (inflateInit(&soap->d_stream) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; + soap->zlib_state = SOAP_ZLIB_INFLATE; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate initialized\n")); + } + soap->mode |= SOAP_ENC_ZLIB; + memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); + soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx); + soap->d_stream.avail_in = soap->buflen - soap->bufidx; + soap->z_buflen = soap->buflen; + soap->buflen = soap->bufidx; + } +#endif + if (soap->error) + { if (soap->error == SOAP_FORM && soap->fform) + { soap->error = soap->fform(soap); + if (soap->error == SOAP_OK) + soap->error = SOAP_STOP; /* prevents further processing */ + } + return soap->error; + } + } +#endif +#ifndef WITH_LEANER + if (soap->mode & SOAP_ENC_MIME) + { if (soap_getmimehdr(soap)) + return soap->error; + if (soap_get_header_attribute(soap, soap->mime.first->type, "application/dime")) + soap->mode |= SOAP_ENC_DIME; + } + if (soap->mode & SOAP_ENC_DIME) + { if (soap_getdimehdr(soap)) + return soap->error; + if (soap->dime.flags & SOAP_DIME_CF) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked DIME SOAP message\n")); + soap->dime.chunksize = soap->dime.size; + if (soap->buflen - soap->bufidx >= soap->dime.chunksize) + { soap->dime.buflen = soap->buflen; + soap->buflen = soap->bufidx + soap->dime.chunksize; + } + else + soap->dime.chunksize -= soap->buflen - soap->bufidx; + } + soap->count = soap->buflen - soap->bufidx; + } +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_parse(struct soap *soap) +{ char header[SOAP_HDRLEN], *s; + unsigned short get = 0, status = 0, k = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Waiting for HTTP request/response...\n")); + *soap->endpoint = '\0'; + soap->length = 0; + soap->userid = NULL; + soap->passwd = NULL; + soap->action = NULL; + soap->authrealm = NULL; + do + { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) + return soap->error; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP status: %s\n", soap->msgbuf)); + for (;;) + { if (soap_getline(soap, header, SOAP_HDRLEN)) + { if (soap->error == SOAP_EOF) + { soap->error = SOAP_OK; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "EOF in HTTP header, continue anyway\n")); + break; + } + return soap->error; + } + if (!*header) + break; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP header: %s\n", header)); + s = strchr(header, ':'); + if (s) + { *s = '\0'; + do s++; + while (*s && *s <= 32); + if ((soap->error = soap->fparsehdr(soap, header, s))) + { if (soap->error < SOAP_STOP) + return soap->error; + status = soap->error; + soap->error = SOAP_OK; + } + } + } + if ((s = strchr(soap->msgbuf, ' '))) + { k = (unsigned short)soap_strtoul(s, &s, 10); + if (!soap_blank(*s)) + k = 0; + } + else + k = 0; + } while (k == 100); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Finished HTTP header parsing\n")); + s = strstr(soap->msgbuf, "HTTP/"); + if (s && s[7] != '1') + { if (soap->keep_alive == 1) + soap->keep_alive = 0; + if (k == 0 && (soap->omode & SOAP_IO) == SOAP_IO_CHUNK) /* k == 0 for HTTP request */ + { soap->imode |= SOAP_IO_CHUNK; + soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE; + } + } + if (soap->keep_alive < 0) + soap->keep_alive = 1; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Keep alive connection = %d\n", soap->keep_alive)); + if (s && (((get = !strncmp(soap->msgbuf, "GET ", 4))) || !strncmp(soap->msgbuf, "POST ", 5))) + { size_t m = strlen(soap->endpoint); + size_t n = m + (s - soap->msgbuf) - 5 - (!get); + if (n >= sizeof(soap->endpoint)) + n = sizeof(soap->endpoint) - 1; + strncpy(soap->path, soap->msgbuf + 4 + (!get), n - m); + soap->path[n - m] = '\0'; + strcat(soap->endpoint, soap->path); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Target endpoint='%s'\n", soap->endpoint)); + if (get) + { soap->error = soap->fget(soap); + if (soap->error == SOAP_OK) + soap->error = SOAP_STOP; /* prevents further processing */ + return soap->error; + } + if (status) + return soap->error = status; + return SOAP_OK; + } + if (k == 0 || (k >= 200 && k <= 299) || k == 400 || k == 500) + return SOAP_OK; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP error %d\n", k)); + return soap_set_receiver_error(soap, "HTTP error", soap->msgbuf, k); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_parse_header(struct soap *soap, const char *key, const char *val) +{ if (!soap_tag_cmp(key, "Host")) + { +#ifdef WITH_OPENSSL + if (soap->imode & SOAP_ENC_SSL) + strcpy(soap->endpoint, "https://"); + else +#endif + strcpy(soap->endpoint, "http://"); + strncat(soap->endpoint, val, sizeof(soap->endpoint) - 8); + soap->endpoint[sizeof(soap->endpoint) - 1] = '\0'; + } +#ifndef WITH_LEANER + else if (!soap_tag_cmp(key, "Content-Type")) + { if (soap_get_header_attribute(soap, val, "application/dime")) + soap->mode |= SOAP_ENC_DIME; + else if (soap_get_header_attribute(soap, val, "multipart/related") + || soap_get_header_attribute(soap, val, "multipart/form-data")) + { soap->mime.boundary = soap_strdup(soap, soap_get_header_attribute(soap, val, "boundary")); + soap->mime.start = soap_strdup(soap, soap_get_header_attribute(soap, val, "start")); + soap->mode |= SOAP_ENC_MIME; + } + } +#endif + else if (!soap_tag_cmp(key, "Content-Length")) + soap->length = soap_strtoul(val, NULL, 10); + else if (!soap_tag_cmp(key, "Content-Encoding")) + { if (!soap_tag_cmp(val, "deflate")) +#ifdef WITH_ZLIB + soap->zlib_in = SOAP_ZLIB_DEFLATE; +#else + return SOAP_ZLIB_ERROR; +#endif + else if (!soap_tag_cmp(val, "gzip")) +#ifdef WITH_GZIP + soap->zlib_in = SOAP_ZLIB_GZIP; +#else + return SOAP_ZLIB_ERROR; +#endif + } +#ifdef WITH_ZLIB + else if (!soap_tag_cmp(key, "Accept-Encoding")) + { +#ifdef WITH_GZIP + if (strchr(val, '*') || soap_get_header_attribute(soap, val, "gzip")) + soap->zlib_out = SOAP_ZLIB_GZIP; + else +#endif + if (strchr(val, '*') || soap_get_header_attribute(soap, val, "deflate")) + soap->zlib_out = SOAP_ZLIB_DEFLATE; + else + soap->zlib_out = SOAP_ZLIB_NONE; + } +#endif + else if (!soap_tag_cmp(key, "Transfer-Encoding")) + { soap->mode &= ~SOAP_IO; + if (!soap_tag_cmp(val, "chunked")) + soap->mode |= SOAP_IO_CHUNK; + } + else if (!soap_tag_cmp(key, "Connection")) + { if (!soap_tag_cmp(val, "keep-alive")) + soap->keep_alive = -soap->keep_alive; + else if (!soap_tag_cmp(val, "close")) + soap->keep_alive = 0; + } +#ifndef WITH_LEAN + else if (!soap_tag_cmp(key, "Authorization")) + { if (!soap_tag_cmp(val, "Basic *")) + { int n; + char *s; + soap_base642s(soap, val + 6, soap->tmpbuf, sizeof(soap->tmpbuf) - 1, &n); + soap->tmpbuf[n] = '\0'; + if ((s = strchr(soap->tmpbuf, ':'))) + { *s = '\0'; + soap->userid = soap_strdup(soap, soap->tmpbuf); + soap->passwd = soap_strdup(soap, s + 1); + } + } + } + else if (!soap_tag_cmp(key, "WWW-Authenticate")) + soap->authrealm = soap_strdup(soap, soap_get_header_attribute(soap, val + 6, "realm")); + else if (!soap_tag_cmp(key, "Expect")) + { if (!soap_tag_cmp(val, "100-continue")) + { if ((soap->error = soap->fposthdr(soap, "HTTP/1.1 100 Continue", NULL)) + || (soap->error = soap->fposthdr(soap, NULL, NULL))) + return soap->error; + } + } +#endif + else if (!soap_tag_cmp(key, "SOAPAction")) + { if (*val == '"') + { soap->action = soap_strdup(soap, val + 1); + soap->action[strlen(soap->action) - 1] = '\0'; + } + } + else if (!soap_tag_cmp(key, "Location")) + { strncpy(soap->endpoint, val, sizeof(soap->endpoint)); + soap->endpoint[sizeof(soap->endpoint) - 1] = '\0'; + } +#ifdef WITH_COOKIES + else if (!soap_tag_cmp(key, "Cookie") || !soap_tag_cmp(key, "Set-Cookie")) + soap_getcookies(soap, val); +#endif + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_get_header_attribute(struct soap *soap, const char *line, const char *key) +{ register const char *s = line; + if (s) + { while (*s) + { register short flag; + s = soap_decode_key(soap->tmpbuf, sizeof(soap->tmpbuf), s); + flag = soap_tag_cmp(soap->tmpbuf, key); + s = soap_decode_val(soap->tmpbuf, sizeof(soap->tmpbuf), s); + if (!flag) + return soap->tmpbuf; + } + } + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_decode_key(char *buf, size_t len, const char *val) +{ return soap_decode(buf, len, val, "=,;"); +} +#endif +#endif + +/******************************************************************************/ +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_decode_val(char *buf, size_t len, const char *val) +{ if (*val != '=') + { *buf = '\0'; + return val; + } + return soap_decode(buf, len, val + 1, ",;"); +} +#endif +#endif + +/******************************************************************************/ +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +#ifndef PALM_1 +static const char* +soap_decode(char *buf, size_t len, const char *val, const char *sep) +{ const char *s; + char *t = buf; + for (s = val; *s; s++) + if (*s != ' ' && *s != '\t' && !strchr(sep, *s)) + break; + if (*s == '"') + { s++; + while (*s && *s != '"' && --len) + *t++ = *s++; + } + else + { while (soap_notblank(*s) && !strchr(sep, *s) && --len) + { if (*s == '%') + { *t++ = ((s[1] >= 'A' ? (s[1] & 0x7) + 9 : s[1] - '0') << 4) + + (s[2] >= 'A' ? (s[2] & 0x7) + 9 : s[2] - '0'); + s += 3; + } + else + *t++ = *s++; + } + } + *t = '\0'; + while (*s && !strchr(sep, *s)) + s++; + return s; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_envelope_begin_out(struct soap *soap) +{ +#ifndef WITH_LEANER + size_t n = 0; + if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && soap->mime.start) + { const char *s; + if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) + s = "application/dime"; + else if (soap->version == 2) + s = "application/soap+xml; charset=utf-8"; + else + s = "text/xml; charset=utf-8"; + sprintf(soap->tmpbuf, "--%s\r\nContent-Type: %s\r\nContent-Transfer-Encoding: binary\r\nContent-ID: %s\r\n\r\n", soap->mime.boundary, s, soap->mime.start); + n = strlen(soap->tmpbuf); + if (soap_send_raw(soap, soap->tmpbuf, n)) + return soap->error; + } + if (soap->mode & SOAP_IO_LENGTH) + soap->dime.size = soap->count; /* DIME in MIME correction */ + if (!(soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME)) + { if (soap_putdimehdr(soap)) + return soap->error; + } +#endif + soap->part = SOAP_IN_ENVELOPE; + return soap_element_begin_out(soap, "SOAP-ENV:Envelope", 0, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_envelope_end_out(struct soap *soap) +{ if (soap_element_end_out(soap, "SOAP-ENV:Envelope")) + return soap->error; +#ifndef WITH_LEANER + if ((soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) + { soap->dime.size = soap->count - soap->dime.size; /* DIME in MIME correction */ + sprintf(soap->id, soap->dime_id_format, 0); + soap->dime.id = soap->id; + if (soap->local_namespaces) + { if (soap->local_namespaces[0].out) + soap->dime.type = (char*)soap->local_namespaces[0].out; + else + soap->dime.type = (char*)soap->local_namespaces[0].ns; + } + soap->dime.options = NULL; + soap->dime.flags = SOAP_DIME_MB | SOAP_DIME_ABSURI; + if (!soap->dime.first) + soap->dime.flags |= SOAP_DIME_ME; + soap->count += 12 + ((strlen(soap->dime.id)+3)&(~3)) + ((strlen(soap->dime.type)+3)&(~3)); + } + if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) + return soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3); +#endif + soap->part = SOAP_END_ENVELOPE; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_envelope_begin_in(struct soap *soap) +{ register struct Namespace *p; + soap->part = SOAP_IN_ENVELOPE; + if (soap_element_begin_in(soap, "SOAP-ENV:Envelope", 0)) + return soap->error = SOAP_VERSIONMISMATCH; + p = soap->local_namespaces; + if (p) + { const char *ns = p[0].out; + if (!ns) + ns = p[0].ns; + if (!strcmp(ns, soap_env1)) + { soap->version = 1; /* make sure we use SOAP 1.1 */ + if (p[1].out) + SOAP_FREE(soap, p[1].out); + if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc1)))) + strcpy(p[1].out, soap_enc1); + } + else if (!strcmp(ns, soap_env2)) + { soap->version = 2; /* make sure we use SOAP 1.2 */ + if (p[1].out) + SOAP_FREE(soap, p[1].out); + if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc2)))) + strcpy(p[1].out, soap_enc2); + } + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_envelope_end_in(struct soap *soap) +{ soap->part = SOAP_END_ENVELOPE; + return soap_element_end_in(soap, "SOAP-ENV:Envelope"); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_body_begin_out(struct soap *soap) +{ soap->part = SOAP_IN_BODY; + if (soap->version == 1) + soap->encoding = 1; +#ifndef WITH_LEAN + if ((soap->mode & SOAP_XML_SEC) && soap_set_attr(soap, "wsu:Id", "Body")) + return soap->error; +#endif + if (soap_element(soap, "SOAP-ENV:Body", 0, NULL)) + return soap->error; + return soap_element_start_end_out(soap, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_body_end_out(struct soap *soap) +{ if (soap_element_end_out(soap, "SOAP-ENV:Body")) + return soap->error; + soap->part = SOAP_END_BODY; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_body_begin_in(struct soap *soap) +{ soap->part = SOAP_IN_BODY; + if (soap_element_begin_in(soap, "SOAP-ENV:Body", 0)) + return soap->error; + if (!soap->body) + soap->part = SOAP_NO_BODY; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_body_end_in(struct soap *soap) +{ if (soap->part == SOAP_NO_BODY) + return SOAP_OK; + soap->part = SOAP_END_BODY; + return soap_element_end_in(soap, "SOAP-ENV:Body"); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv_header(struct soap *soap) +{ if (soap_getheader(soap) && soap->error == SOAP_TAG_MISMATCH) + soap->error = SOAP_OK; + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_endpoint(struct soap *soap, const char *endpoint) +{ register const char *s; + register size_t i, n; + soap->endpoint[0] = '\0'; + soap->host[0] = '\0'; + soap->path[0] = '/'; + soap->path[1] = '\0'; + soap->port = 80; + if (!endpoint || !*endpoint) + return; + if (!strncmp(endpoint, "https:", 6)) + soap->port = 443; + strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint) - 1); + s = strchr(endpoint, ':'); + if (s && s[1] == '/' && s[2] == '/') + s += 3; + else + s = endpoint; + n = strlen(s); + if (n >= sizeof(soap->host)) + n = sizeof(soap->host) - 1; +#ifdef WITH_IPV6 + if (s[0] == '[') + { s++; + for (i = 0; i < n; i++) + { soap->host[i] = s[i]; + if (s[i] == ']') + { s++; + break; + } + } + } + else + { for (i = 0; i < n; i++) + { soap->host[i] = s[i]; + if (s[i] == '/' || s[i] == ':') + break; + } + } +#else + for (i = 0; i < n; i++) + { soap->host[i] = s[i]; + if (s[i] == '/' || s[i] == ':') + break; + } +#endif + soap->host[i] = '\0'; + if (s[i] == ':') + { soap->port = (int)atol(s + i + 1); + for (i++; i < n; i++) + if (s[i] == '/') + break; + } + if (s[i]) + { strncpy(soap->path, s + i, sizeof(soap->path)); + soap->path[sizeof(soap->path) - 1] = '\0'; + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_connect(struct soap *soap, const char *endpoint, const char *action) +{ return soap_connect_command(soap, SOAP_POST, endpoint, action); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_connect_command(struct soap *soap, int http_command, const char *endpoint, const char *action) +{ char host[sizeof(soap->host)]; + int port; + size_t count; + soap->error = SOAP_OK; + strcpy(host, soap->host); /* save to compare */ + port = soap->port; /* save to compare */ + soap_set_endpoint(soap, endpoint); +#ifndef WITH_LEANER + if (soap->fconnect) + { if ((soap->error = soap->fconnect(soap, endpoint, soap->host, soap->port))) + return soap->error; + } + else +#endif + if (soap->fopen && *soap->host) + { soap->status = http_command; + if (!soap->keep_alive || !soap_valid_socket(soap->socket) || strcmp(soap->host, host) || soap->port != port || !soap->fpoll || soap->fpoll(soap)) + { soap->keep_alive = 0; /* to force close */ + soap->omode &= ~SOAP_IO_UDP; /* to force close */ + soap_closesock(soap); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Connect/reconnect to host='%s' path='%s' port=%d\n", soap->host, soap->path, soap->port)); +#ifdef WITH_UDP + if (!strncmp(endpoint, "soap.udp:", 9)) + soap->omode |= SOAP_IO_UDP; +#endif + soap->socket = soap->fopen(soap, endpoint, soap->host, soap->port); + if (soap->error) + return soap->error; + soap->keep_alive = ((soap->omode & SOAP_IO_KEEPALIVE) != 0); + } + } + count = soap_count_attachments(soap); + if (soap_begin_send(soap)) + return soap->error; +#ifndef WITH_NOHTTP + if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML) && endpoint) + { unsigned int k = soap->mode; + soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB); + if ((k & SOAP_IO) != SOAP_IO_FLUSH) + soap->mode |= SOAP_IO_BUFFER; + if ((soap->error = soap->fpost(soap, endpoint, soap->host, soap->port, soap->path, action, count))) + return soap->error; +#ifndef WITH_LEANER + if ((k & SOAP_IO) == SOAP_IO_CHUNK) + { if (soap_flush(soap)) + return soap->error; + } +#endif + soap->mode = k; + } + else if (action) + soap->action = soap_strdup(soap, action); + if (http_command != SOAP_POST) + return soap_end_send(soap); +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_s2base64(struct soap *soap, const unsigned char *s, char *t, int n) +{ register int i; + register unsigned long m; + register char *p; + if (!t) + t = (char*)soap_malloc(soap, (n + 2) / 3 * 4 + 1); + if (!t) + { soap->error = SOAP_EOM; + return NULL; + } + p = t; + t[0] = '\0'; + if (!s) + return p; + for (; n > 2; n -= 3, s += 3) + { m = s[0]; + m = (m << 8) | s[1]; + m = (m << 8) | s[2]; + for (i = 4; i > 0; m >>= 6) + t[--i] = soap_base64o[m & 0x3F]; + t += 4; + } + t[0] = '\0'; + if (n > 0) + { m = 0; + for (i = 0; i < n; i++) + m = (m << 8) | *s++; + for (; i < 3; i++) + m <<= 8; + for (i++; i > 0; m >>= 6) + t[--i] = soap_base64o[m & 0x3F]; + for (i = 3; i > n; i--) + t[i] = '='; + t[4] = '\0'; + } + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_base642s(struct soap *soap, const char *s, char *t, size_t l, int *n) +{ register int i, j, c; + register unsigned long m; + register const char *p; + if (!s || !*s) + { if (n) + *n = 0; + if (soap->error) + return NULL; + return SOAP_NON_NULL; + } + if (!t) + { l = (strlen(s) + 3) / 4 * 3; + t = (char*)soap_malloc(soap, l); + } + if (!t) + { soap->error = SOAP_EOM; + return NULL; + } + p = t; + if (n) + *n = 0; + for (;;) + { for (i = 0; i < SOAP_BLKLEN; i++) + { m = 0; + j = 0; + while (j < 4) + { c = *s++; + if (c == '=' || !c) + { i *= 3; + switch (j) + { case 2: + *t++ = (char)((m >> 4) & 0xFF); + i++; + break; + case 3: + *t++ = (char)((m >> 10) & 0xFF); + *t++ = (char)((m >> 2) & 0xFF); + i += 2; + } + if (n) + *n += i; + return p; + } + c -= '+'; + if (c >= 0 && c <= 79) + { m = (m << 6) + soap_base64i[c]; + j++; + } + } + *t++ = (char)((m >> 16) & 0xFF); + *t++ = (char)((m >> 8) & 0xFF); + *t++ = (char)(m & 0xFF); + if (l < 3) + { if (n) + *n += i; + return p; + } + l -= 3; + } + if (n) + *n += 3 * SOAP_BLKLEN; + } +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_s2hex(struct soap *soap, const unsigned char *s, char *t, int n) +{ register char *p; + if (!t) + t = (char*)soap_malloc(soap, 2 * n + 1); + if (!t) + { soap->error = SOAP_EOM; + return NULL; + } + p = t; + t[0] = '\0'; + if (s) + { for (; n > 0; n--) + { register int m = *s++; + *t++ = (char)((m >> 4) + (m > 159 ? 'a' - 10 : '0')); + m &= 0x0F; + *t++ = (char)(m + (m > 9 ? 'a' - 10 : '0')); + } + } + *t++ = '\0'; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_hex2s(struct soap *soap, const char *s, char *t, size_t l, int *n) +{ register const char *p; + if (!s || !*s) + { if (n) + *n = 0; + if (soap->error) + return NULL; + return SOAP_NON_NULL; + } + if (!t) + { l = strlen(s) / 2; + t = (char*)soap_malloc(soap, l); + } + if (!t) + { soap->error = SOAP_EOM; + return NULL; + } + p = t; + while (l) + { register int d1, d2; + d1 = *s++; + if (!d1) + break; + d2 = *s++; + if (!d2) + break; + *t++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'); + l--; + } + if (n) + *n = t - p; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_puthttphdr(struct soap *soap, int status, size_t count) +{ register const char *s; +#ifndef WITH_LEANER + register const char *r = NULL; +#endif + register int err; + if (status == SOAP_FILE && soap->http_content) + s = soap->http_content; + else if (status == SOAP_HTML) + s = "text/html; charset=utf-8"; + else if (soap->version == 2) + s = "application/soap+xml; charset=utf-8"; + else + s = "text/xml; charset=utf-8"; +#ifndef WITH_LEANER + if (soap->mode & (SOAP_ENC_DIME | SOAP_ENC_MTOM)) + { if (soap->mode & SOAP_ENC_MTOM) + { r = s; + s = "application/xop+xml; charset=utf-8"; + } + else + s = "application/dime"; + } + if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && soap->status != SOAP_GET) + { register const char *t = strchr(s, ';'); + sprintf(soap->tmpbuf, "multipart/related; boundary=\"%s\"; type=\"", soap->mime.boundary); + if (t) + strncat(soap->tmpbuf, s, t - s); + else + strcat(soap->tmpbuf, s); + if (soap->mime.start) + { strcat(soap->tmpbuf, "\"; start=\""); + strcat(soap->tmpbuf, soap->mime.start); + } + strcat(soap->tmpbuf, "\""); + if (r) + { strcat(soap->tmpbuf, "; start-info=\""); + strcat(soap->tmpbuf, r); + strcat(soap->tmpbuf, "\""); + } + s = soap->tmpbuf; + } +#endif + if ((err = soap->fposthdr(soap, "Content-Type", s))) + return err; +#ifdef WITH_ZLIB + if (soap->omode & SOAP_ENC_ZLIB) + { +#ifdef WITH_GZIP + err = soap->fposthdr(soap, "Content-Encoding", "gzip"); +#else + err = soap->fposthdr(soap, "Content-Encoding", "deflate"); +#endif + if (err) + return err; + } +#endif +#ifndef WITH_LEANER + if ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK) + err = soap->fposthdr(soap, "Transfer-Encoding", "chunked"); + else +#endif + if (count > 0) + { sprintf(soap->tmpbuf, "%lu", (unsigned long)count); + err = soap->fposthdr(soap, "Content-Length", soap->tmpbuf); + } + if (err) + return err; + return soap->fposthdr(soap, "Connection", soap->keep_alive ? "keep-alive" : "close"); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_get(struct soap *soap) +{ return SOAP_GET_METHOD; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_post(struct soap *soap, const char *endpoint, const char *host, int port, const char *path, const char *action, size_t count) +{ register const char *s; + register int err; + if (soap->status == SOAP_GET) + { s = "GET"; + count = 0; + } + else + s = "POST"; +#ifdef PALM + if (!endpoint || (strncmp(endpoint, "http:", 5) && strncmp(endpoint, "https:", 6) && strncmp(endpoint, "httpg:", 6)) && strncmp(endpoint, "_beam:", 6) && strncmp(endpoint, "_local:", 7) && strncmp(endpoint, "_btobex:", 8)) +#else + if (!endpoint || (strncmp(endpoint, "http:", 5) && strncmp(endpoint, "https:", 6) && strncmp(endpoint, "httpg:", 6))) +#endif + return SOAP_OK; + if (soap->proxy_host && strncmp(endpoint, "https:", 6)) + sprintf(soap->tmpbuf, "%s %s HTTP/%s", s, endpoint, soap->http_version); + else + sprintf(soap->tmpbuf, "%s /%s HTTP/%s", s, (*path == '/' ? path + 1 : path), soap->http_version); + if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return err; + if (port != 80) + sprintf(soap->tmpbuf, "%s:%d", host, port); + else + strcpy(soap->tmpbuf, host); + if ((err = soap->fposthdr(soap, "Host", soap->tmpbuf)) + || (err = soap->fposthdr(soap, "User-Agent", "gSOAP/2.7")) + || (err = soap_puthttphdr(soap, SOAP_OK, count))) + return err; +#ifdef WITH_ZLIB +#ifdef WITH_GZIP + if ((err = soap->fposthdr(soap, "Accept-Encoding", "gzip, deflate"))) +#else + if ((err = soap->fposthdr(soap, "Accept-Encoding", "deflate"))) +#endif + return err; +#endif +#ifndef WITH_LEAN + if (soap->userid && soap->passwd && strlen(soap->userid) + strlen(soap->passwd) < 761) + { sprintf(soap->tmpbuf + 262, "%s:%s", soap->userid, soap->passwd); + strcpy(soap->tmpbuf, "Basic "); + soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, strlen(soap->tmpbuf + 262)); + if ((err = soap->fposthdr(soap, "Authorization", soap->tmpbuf))) + return err; + } + if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761) + { sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd); + strcpy(soap->tmpbuf, "Basic "); + soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, strlen(soap->tmpbuf + 262)); + if ((err = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf))) + return err; + } +#endif +#ifdef WITH_COOKIES +#ifdef WITH_OPENSSL + if (soap_putcookies(soap, host, path, soap->ssl != NULL)) + return soap->error; +#else + if (soap_putcookies(soap, host, path, 0)) + return soap->error; +#endif +#endif + if (action && soap->version == 1) + { sprintf(soap->tmpbuf, "\"%s\"", action); + if ((err = soap->fposthdr(soap, "SOAPAction", soap->tmpbuf))) + return err; + } + return soap->fposthdr(soap, NULL, NULL); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_send_header(struct soap *soap, const char *s) +{ register const char *t; + do + { t = strchr(s, '\n'); /* disallow \n in HTTP headers */ + if (!t) + t = s + strlen(s); + if (soap_send_raw(soap, s, t - s)) + return soap->error; + s = t + 1; + } while (*t); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_post_header(struct soap *soap, const char *key, const char *val) +{ if (key) + { if (http_send_header(soap, key)) + return soap->error; + if (val && (soap_send_raw(soap, ": ", 2) || http_send_header(soap, val))) + return soap->error; + } + return soap_send_raw(soap, "\r\n", 2); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_response(struct soap *soap, int status, size_t count) +{ register int err; +#ifdef WMW_RPM_IO + if (soap->rpmreqid) + httpOutputEnable(soap->rpmreqid); +#endif /* WMW_RPM_IO */ + if (!status || status == SOAP_HTML || status == SOAP_FILE) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "OK 200\n")); +#ifdef WMW_RPM_IO + if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */ +#else + if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application */ +#endif /* WMW_RPM_IO */ + { sprintf(soap->tmpbuf, "HTTP/%s 200 OK", soap->http_version); + if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return err; + } + else if ((err = soap->fposthdr(soap, "Status", "200 OK"))) + return err; + } + else if (status > 200 && status < 600) + { sprintf(soap->tmpbuf, "HTTP/%s %d %s", soap->http_version, status, http_error(soap, status)); + if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return err; +#ifndef WITH_LEAN + if (status == 401) + { sprintf(soap->tmpbuf, "Basic realm=\"%s\"", soap->authrealm ? soap->authrealm : "gSOAP Web Service"); + if ((err = soap->fposthdr(soap, "WWW-Authenticate", soap->tmpbuf))) + return err; + } + else if ((status >= 301 && status <= 303) || status == 307) + { if ((err = soap->fposthdr(soap, "Location", soap->endpoint))) + return err; + } +#endif + } + else + { const char *s = *soap_faultcode(soap); + if (soap->version == 2 && !strcmp(s, "SOAP-ENV:Sender")) + s = "400 Bad Request"; + else + s = "500 Internal Server Error"; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error %s (status=%d)\n", s, status)); +#ifdef WMW_RPM_IO + if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */ +#else + if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application */ +#endif /* WMW_RPM_IO */ + { sprintf(soap->tmpbuf, "HTTP/%s %s", soap->http_version, s); + if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return err; + } + else if ((err = soap->fposthdr(soap, "Status", s))) + return err; + } + if ((err = soap->fposthdr(soap, "Server", "gSOAP/2.7")) + || (err = soap_puthttphdr(soap, status, count))) + return err; +#ifdef WITH_COOKIES + if (soap_putsetcookies(soap)) + return soap->error; +#endif + return soap->fposthdr(soap, NULL, NULL); +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_response(struct soap *soap, int status) +{ register size_t count; + if (!(soap->omode & (SOAP_ENC_XML | SOAP_IO_STORE /* this tests for chunking too */)) + && (status == SOAP_HTML || status == SOAP_FILE)) + { soap->omode &= ~SOAP_IO; + soap->omode |= SOAP_IO_STORE; + } + soap->status = status; + count = soap_count_attachments(soap); + if (soap_begin_send(soap)) + return soap->error; +#ifndef WITH_NOHTTP + if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML)) + { register int n = soap->mode; + soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB); + if ((n & SOAP_IO) != SOAP_IO_FLUSH) + soap->mode |= SOAP_IO_BUFFER; + if ((soap->error = soap->fresponse(soap, status, count))) + return soap->error; +#ifndef WITH_LEANER + if ((n & SOAP_IO) == SOAP_IO_CHUNK) + { if (soap_flush(soap)) + return soap->error; + } +#endif + soap->mode = n; + } +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static const char* +soap_set_validation_fault(struct soap *soap, const char *s, const char *t) +{ if (*soap->tag) + sprintf(soap->msgbuf, "Validation constraint violation: %s%s in element <%s>", s, t?t:SOAP_STR_EOS, soap->tag); + else + sprintf(soap->msgbuf, "Validation constraint violation: %s%s", s, t?t:SOAP_STR_EOS); + return soap->msgbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_fault(struct soap *soap) +{ const char **c = soap_faultcode(soap); + const char **s = soap_faultstring(soap); + if (!*c && !*s && soap->fseterror) + soap->fseterror(soap, c, s); + if (!*c) + { if (soap->version == 2) + *c = "SOAP-ENV:Sender"; + else + *c = "SOAP-ENV:Client"; + } + if (*s) + return; + switch (soap->error) + { +#ifndef WITH_LEAN + case SOAP_CLI_FAULT: + *s = "Client fault"; + break; + case SOAP_SVR_FAULT: + *s = "Server fault"; + break; + case SOAP_TAG_MISMATCH: + *s = soap_set_validation_fault(soap, "tag name or namespace mismatch", NULL); + break; + case SOAP_TYPE: + *s = soap_set_validation_fault(soap, "data type mismatch ", soap->type); + break; + case SOAP_SYNTAX_ERROR: + *s = "Well-formedness violation"; + break; + case SOAP_NO_TAG: + *s = "No XML element tag"; + break; + case SOAP_MUSTUNDERSTAND: + *c = "SOAP-ENV:MustUnderstand"; + sprintf(soap->msgbuf, "The data in element '%s' must be understood but cannot be handled", soap->tag); + *s = soap->msgbuf; + break; + case SOAP_VERSIONMISMATCH: + *c = "SOAP-ENV:VersionMismatch"; + *s = "SOAP version mismatch or invalid SOAP message"; + break; + case SOAP_DATAENCODINGUNKNOWN: + *c = "SOAP-ENV:DataEncodingUnknown"; + *s = "Unsupported SOAP data encoding"; + break; + case SOAP_NAMESPACE: + *s = soap_set_validation_fault(soap, "namespace mismatch", NULL); + break; + case SOAP_USER_ERROR: + *s = "User error"; + break; + case SOAP_FATAL_ERROR: + *s = "Fatal error"; + break; + case SOAP_NO_METHOD: + sprintf(soap->msgbuf, "Method '%s' not implemented: method name or namespace not recognized", soap->tag); + *s = soap->msgbuf; + break; + case SOAP_GET_METHOD: + *s = "HTTP GET method not implemented"; + break; + case SOAP_EOM: + *s = "Out of memory"; + break; + case SOAP_IOB: + *s = "Array index out of bounds"; + break; + case SOAP_NULL: + *s = soap_set_validation_fault(soap, "nil not allowed", NULL); + break; + case SOAP_DUPLICATE_ID: + *s = soap_set_validation_fault(soap, "multiple definitions of id ", soap->id); + if (soap->version == 2) + *soap_faultsubcode(soap) = "SOAP-ENC:DuplicateID"; + break; + case SOAP_MISSING_ID: + *s = soap_set_validation_fault(soap, "missing id for ref ", soap->id); + if (soap->version == 2) + *soap_faultsubcode(soap) = "SOAP-ENC:MissingID"; + break; + case SOAP_HREF: + *s = soap_set_validation_fault(soap, "incompatible object ref ", soap->id); + break; + case SOAP_FAULT: + break; +#ifndef WITH_NOIO + case SOAP_UDP_ERROR: + *s = "Message too large for UDP packet"; + break; + case SOAP_TCP_ERROR: + *s = tcp_error(soap); + break; +#endif + case SOAP_HTTP_ERROR: + *s = "HTTP error"; + break; + case SOAP_SSL_ERROR: +#ifdef WITH_OPENSSL + *s = "SSL error"; +#else + *s = "OpenSSL not installed: recompile with -DWITH_OPENSSL"; +#endif + break; + case SOAP_PLUGIN_ERROR: + *s = "Plugin registry error"; + break; + case SOAP_DIME_ERROR: + *s = "DIME format error"; + break; + case SOAP_DIME_HREF: + *s = "DIME href to missing attachment"; + break; + case SOAP_DIME_MISMATCH: + *s = "DIME version/transmission error"; + break; + case SOAP_DIME_END: + *s = "End of DIME error"; + break; + case SOAP_MIME_ERROR: + *s = "MIME format error"; + break; + case SOAP_MIME_HREF: + *s = "MIME href to missing attachment"; + break; + case SOAP_MIME_END: + *s = "End of MIME error"; + break; + case SOAP_ZLIB_ERROR: +#ifdef WITH_ZLIB + sprintf(soap->msgbuf, "Zlib/gzip error: '%s'", soap->d_stream.msg?soap->d_stream.msg:""); + *s = soap->msgbuf; +#else + *s = "Zlib/gzip not installed for (de)compression: recompile with -DWITH_GZIP"; +#endif + break; + case SOAP_REQUIRED: + *s = soap_set_validation_fault(soap, "missing required attribute", NULL); + break; + case SOAP_PROHIBITED: + *s = soap_set_validation_fault(soap, "prohibited attribute present", NULL); + break; + case SOAP_OCCURS: + *s = soap_set_validation_fault(soap, "min/maxOccurs violation", NULL); + break; + case SOAP_LENGTH: + *s = soap_set_validation_fault(soap, "content length violation", NULL); + break; + case SOAP_STOP: + *s = "Stopped: no response sent"; + break; +#endif + case SOAP_EOF: +#ifndef WITH_NOIO + sprintf(soap->msgbuf, "End of file or no input: '%s'", soap_strerror(soap)); + *s = soap->msgbuf; + break; +#else + *s = "End of file or no input"; + break; +#endif + default: +#ifndef WITH_NOHTTP +#ifndef WITH_LEAN + if (soap->error > 200 && soap->error < 600) + { sprintf(soap->msgbuf, "HTTP Error: %d %s", soap->error, http_error(soap, soap->error)); + *s = soap->msgbuf; + } + else +#endif +#endif + { sprintf(soap->msgbuf, "Error %d", soap->error); + *s = soap->msgbuf; + } + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send_fault(struct soap *soap) +{ register int status = soap->error; + int r = 1; + if (status == SOAP_STOP) + return status; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Sending back fault struct for error code %d\n", soap->error)); + soap->keep_alive = 0; /* to terminate connection */ + soap_set_fault(soap); +#ifndef WITH_NOIO +#ifndef WITH_LEAN + if (soap_valid_socket(soap->socket)) + { struct timeval timeout; + fd_set rfd, sfd; + timeout.tv_sec = 0; + timeout.tv_usec = 0; + FD_ZERO(&rfd); + FD_ZERO(&sfd); + FD_SET((SOAP_SOCKET)soap->socket, &rfd); + FD_SET((SOAP_SOCKET)soap->socket, &sfd); + r = select((SOAP_SOCKET)(soap->socket + 1), &rfd, &sfd, NULL, &timeout); + if (r > 0) + { if (!FD_ISSET((SOAP_SOCKET)soap->socket, &sfd) + || (FD_ISSET((SOAP_SOCKET)soap->socket, &rfd) + && recv((SOAP_SOCKET)soap->socket, soap->tmpbuf, 1, MSG_PEEK) < 0)) + r = 0; + } + } +#endif +#endif + if ((status != SOAP_EOF || (!soap->recv_timeout && !soap->send_timeout)) && r > 0) + { soap->error = SOAP_OK; + soap_serializeheader(soap); + soap_serializefault(soap); + soap_begin_count(soap); + if (soap->mode & SOAP_IO_LENGTH) + { soap_envelope_begin_out(soap); + soap_putheader(soap); + soap_body_begin_out(soap); + soap_putfault(soap); + soap_body_end_out(soap); + soap_envelope_end_out(soap); + } + soap_end_count(soap); + if (soap_response(soap, status) + || soap_envelope_begin_out(soap) + || soap_putheader(soap) + || soap_body_begin_out(soap) + || soap_putfault(soap) + || soap_body_end_out(soap) + || soap_envelope_end_out(soap)) + return soap_closesock(soap); + soap_end_send(soap); + } + soap->error = status; + return soap_closesock(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv_fault(struct soap *soap) +{ register int status = soap->error; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Receiving SOAP Fault\n")); + soap->error = SOAP_OK; + if (soap_getfault(soap)) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Error: soap_get_soapfault() failed. Is this a SOAP message at all?\n")); + *soap_faultcode(soap) = (soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client"); + soap->error = status; + soap_set_fault(soap); + } + else + { register const char *s = *soap_faultcode(soap); + if (!soap_match_tag(soap, s, "SOAP-ENV:Server") || !soap_match_tag(soap, s, "SOAP-ENV:Receiver")) + status = SOAP_SVR_FAULT; + else if (!soap_match_tag(soap, s, "SOAP-ENV:Client") || !soap_match_tag(soap, s, "SOAP-ENV:Sender")) + status = SOAP_CLI_FAULT; + else if (!soap_match_tag(soap, s, "SOAP-ENV:MustUnderstand")) + status = SOAP_MUSTUNDERSTAND; + else if (!soap_match_tag(soap, s, "SOAP-ENV:VersionMismatch")) + status = SOAP_VERSIONMISMATCH; + else + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Fault code %s\n", s)); + status = SOAP_FAULT; + } + if (soap_body_end_in(soap) + || soap_envelope_end_in(soap) + || soap_end_recv(soap)) + return soap_closesock(soap); + soap->error = status; + } + return soap_closesock(soap); +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send_empty_response(struct soap *soap) +{ soap->count = 0; + if (soap_response(soap, SOAP_OK) || soap_end_send(soap)) + return soap_closesock(soap); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv_empty_response(struct soap *soap) +{ if (soap_begin_recv(soap) || soap_end_recv(soap)) + return soap_closesock(soap); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static const char* +soap_strerror(struct soap *soap) +{ register int err = soap->errnum; + if (err) + { +#ifndef WIN32 + return strerror(err); +#else + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0, (LPTSTR)&soap->errorstr, sizeof(soap->errorstr), NULL); + return soap->errorstr; +#endif + } + return "Operation interrupted or timed out"; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +static int +soap_set_error(struct soap *soap, const char *faultcode, const char *faultsubcode, const char *faultstring, const char *faultdetail, int soaperror) +{ *soap_faultcode(soap) = faultcode; + if (faultsubcode) + *soap_faultsubcode(soap) = faultsubcode; + *soap_faultstring(soap) = faultstring; + if (faultdetail && *faultdetail) + { register const char **s = soap_faultdetail(soap); + if (s) + *s = faultdetail; + } + return soap->error = soaperror; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_sender_error(struct soap *soap, const char *faultstring, const char *faultdetail, int soaperror) +{ return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", NULL, faultstring, faultdetail, soaperror); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_receiver_error(struct soap *soap, const char *faultstring, const char *faultdetail, int soaperror) +{ return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", NULL, faultstring, faultdetail, soaperror); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +static int +soap_copy_fault(struct soap *soap, const char *faultcode, const char *faultsubcode, const char *faultstring, const char *faultdetail) +{ char *r = NULL, *s = NULL, *t = NULL; + if (faultsubcode) + r = soap_strdup(soap, faultsubcode); + if (faultstring) + s = soap_strdup(soap, faultstring); + if (faultdetail) + t = soap_strdup(soap, faultdetail); + return soap_set_error(soap, faultcode, r, s, t, SOAP_FAULT); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_sender_fault(struct soap *soap, const char *faultstring, const char *faultdetail) +{ return soap_sender_fault_subcode(soap, NULL, faultstring, faultdetail); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_sender_fault_subcode(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail) +{ return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", faultsubcode, faultstring, faultdetail); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_receiver_fault(struct soap *soap, const char *faultstring, const char *faultdetail) +{ return soap_receiver_fault_subcode(soap, NULL, faultstring, faultdetail); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_receiver_fault_subcode(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail) +{ return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", faultsubcode, faultstring, faultdetail); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +#ifndef WITH_NOSTDLIB +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_print_fault(struct soap *soap, FILE *fd) +{ if (soap->error) + { const char *c, *v = NULL, *s, **d; + d = soap_faultcode(soap); + if (!*d) + soap_set_fault(soap); + c = *d; + if (soap->version == 2) + v = *soap_faultsubcode(soap); + s = *soap_faultstring(soap); + d = soap_faultdetail(soap); + fprintf(fd, "%s%d fault: %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, c, v ? v : "no subcode", s ? s : "[no reason]", d && *d ? *d : "[no detail]"); + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +#ifndef WITH_NOSTDLIB +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_print_fault_location(struct soap *soap, FILE *fd) +{ +#ifndef WITH_LEAN + int i, j, c1, c2; + if (soap->error && soap->buflen > 0) + { i = (int)soap->bufidx - 1; + if (i <= 0) + i = 0; + c1 = soap->buf[i]; + soap->buf[i] = '\0'; + if ((int)soap->buflen >= i + 1024) + j = i + 1023; + else + j = (int)soap->buflen - 1; + c2 = soap->buf[j]; + soap->buf[j] = '\0'; + fprintf(fd, "%s%c\n** HERE **\n", soap->buf, c1); + if (soap->bufidx < soap->buflen) + fprintf(fd, "%s\n", soap->buf + soap->bufidx); + soap->buf[i] = c1; + soap->buf[j] = c2; + } +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_register_plugin_arg(struct soap *soap, int (*fcreate)(struct soap*, struct soap_plugin*, void*), void *arg) +{ register struct soap_plugin *p; + register int r; + if (!(p = (struct soap_plugin*)SOAP_MALLOC(soap, sizeof(struct soap_plugin)))) + return soap->error = SOAP_EOM; + p->id = NULL; + p->data = NULL; + p->fcopy = NULL; + p->fdelete = NULL; + r = fcreate(soap, p, arg); + if (!r && p->fdelete) + { p->next = soap->plugins; + soap->plugins = p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Registered '%s' plugin\n", p->id)); + return SOAP_OK; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not register plugin '%s': plugin returned error %d (or fdelete callback not set)\n", p->id?p->id:"?", r)); + SOAP_FREE(soap, p); + return r; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static void * +fplugin(struct soap *soap, const char *id) +{ register struct soap_plugin *p; + for (p = soap->plugins; p; p = p->next) + if (p->id == id || !strcmp(p->id, id)) + return p->data; + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void * +SOAP_FMAC2 +soap_lookup_plugin(struct soap *soap, const char *id) +{ return soap->fplugin(soap, id); +} +#endif + +/******************************************************************************/ +#ifdef __cplusplus +} +#endif + diff --git a/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.6b.h b/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.6b.h new file mode 100644 index 0000000..17ef597 --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.6b.h @@ -0,0 +1,2053 @@ +/* + +stdsoap2.h 2.7.6b + +gSOAP runtime + +gSOAP XML Web services tools +Copyright (C) 2000-2005, Robert van Engelen, Genivia Inc., All Rights Reserved. +This part of the software is released under one of the following licenses: +GPL, the gSOAP public license, or Genivia's license for commercial use. +-------------------------------------------------------------------------------- +Contributors: + +Wind River Systems, Inc., for the following additions (marked WR[...]): + - vxWorks compatible +-------------------------------------------------------------------------------- +gSOAP public license. + +The contents of this file are subject to the gSOAP Public License Version 1.3 +(the "License"); you may not use this file except in compliance with the +License. You may obtain a copy of the License at +http://www.cs.fsu.edu/~engelen/soaplicense.html +Software distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +for the specific language governing rights and limitations under the License. + +The Initial Developer of the Original Code is Robert A. van Engelen. +Copyright (C) 2000-2005, Robert van Engelen, Genivia Inc., All Rights Reserved. +-------------------------------------------------------------------------------- +GPL license. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA + +Author contact information: +engelen@genivia.com / engelen@acm.org +-------------------------------------------------------------------------------- +A commercial use license is available from Genivia, Inc., contact@genivia.com +-------------------------------------------------------------------------------- +*/ + +#ifdef WITH_SOAPDEFS_H +# include "soapdefs.h" /* include user-defined stuff */ +#endif + +#ifndef _THREAD_SAFE +# define _THREAD_SAFE +#endif + +#ifndef OPENSERVER +# ifndef _REENTRANT +# define _REENTRANT +# endif +#endif + +#ifndef SOAP_FMAC1 /* stdsoap2.h declaration macro */ +# define SOAP_FMAC1 +#endif + +#ifndef SOAP_FMAC2 /* stdsoap2.h declaration macro */ +# define SOAP_FMAC2 +#endif + +#ifndef SOAP_FMAC3 /* (de)serializer declaration macro */ +# define SOAP_FMAC3 +#endif + +#ifndef SOAP_FMAC3S /* string converter for (de)serializer declaration macro */ +# define SOAP_FMAC3S SOAP_FMAC3 +#endif + +#ifndef SOAP_FMAC4 /* (de)serializer declaration macro */ +# define SOAP_FMAC4 +#endif + +#ifndef SOAP_FMAC4S /* string converter for (de)serializer declaration macro */ +# define SOAP_FMAC4S SOAP_FMAC4 +#endif + +#ifndef SOAP_FMAC5 /* stub/skeleton declaration macro */ +# define SOAP_FMAC5 +#endif + +#ifndef SOAP_FMAC6 /* stub/skeleton declaration macro */ +# define SOAP_FMAC6 +#endif + +#ifndef SOAP_CMAC /* class declaration macro */ +# define SOAP_CMAC +#endif + +#ifndef SOAP_NMAC /* namespace table declaration macro */ +# define SOAP_NMAC +#endif + +#ifndef SOAP_SOURCE_STAMP +# define SOAP_SOURCE_STAMP(str) +#endif + +/* gSOAP 2.7.4 and higher: fast look-aside buffering is stable */ +#ifndef WITH_FAST +# define WITH_FAST +#endif + +#ifdef WITH_LEANER +# ifndef WITH_LEAN +# define WITH_LEAN +# endif +#endif + +#ifdef WITH_LEAN +# ifdef WITH_COOKIES +# error "Cannot build WITH_LEAN code WITH_COOKIES enabled" +# endif +#endif + +#ifndef STDSOAP_H +#define STDSOAP_H + +#if defined(__vxworks) || defined(__VXWORKS__) +# define VXWORKS +#endif + +#ifdef _WIN32 +# ifndef WIN32 +# define WIN32 +# endif +#endif + +#ifdef UNDER_CE +# ifndef WIN32 +# define WIN32 +# endif +#endif + +#ifdef __BORLANDC__ +# ifdef __WIN32__ +# ifndef WIN32 +# define WIN32 +# endif +# endif +#endif + +#ifdef __CYGWIN__ +# ifndef CYGWIN +# define CYGWIN +# endif +#endif + +#ifdef __SYMBIAN32__ +# define SYMBIAN +# undef WIN32 +#endif + +#if defined(__palmos__) || defined(PALM_GCC) || defined(__PALMOS_TRAPS__) +# ifndef PALM +# define PALM +# endif +#endif + +#if defined(__hpux) +# ifndef HP_UX +# define HP_UX +# endif +#endif + +#if defined(__alpha) && !defined(__VMS) +# ifndef TRU64 +# define TRU64 +# endif +#endif + +#ifdef __MVS__ +# ifndef OS390 +# define OS390 +# endif +#endif + +#ifdef HAVE_CONFIG_H +# include "config.h" +# ifdef WITH_OPENSSL +# ifndef HAVE_OPENSSL_SSL_H +# undef WITH_OPENSSL +# endif +# endif +#else +# if defined(UNDER_CE) +# define WITH_LEAN +# define HAVE_SSCANF +# elif defined(WIN32) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# define SOAP_LONG_FORMAT "%I64d" +# define SOAP_ULONG_FORMAT "%I64u" +# elif defined(CYGWIN) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(__APPLE__) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_TIMEGM +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(_AIXVERSION_431) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(HP_UX) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(FREEBSD) || defined(__FreeBSD__) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_STRTOLL +# define HAVE_STRTOULL +# define HAVE_GETTIMEOFDAY +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# define SOAP_LONG_FORMAT "%qd" +# define SOAP_ULONG_FORMAT "%qu" +# elif defined(__VMS) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(__GLIBC__) || defined(__GNU__) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_STRTOLL +# define HAVE_STRTOULL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_TIMEGM +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# define HAVE_ISNAN +# elif defined(TRU64) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_STRTOLL +# define HAVE_STRTOULL +# define HAVE_GETTIMEOFDAY +# define HAVE_SYS_TIMEB_H +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define __USE_STD_IOSTREAM +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# define SOAP_LONG_FORMAT "%ld" +# define SOAP_ULONG_FORMAT "%lu" +# elif defined(MAC_CARBON) +# define WITH_NOIO +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GETHOSTBYNAME_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(PALM) +# define WITH_LEAN +# define HAVE_STRTOD /* strtod() is defined in palmFunctions.h */ +# include /* Needs to be included before unix headers */ +# include +# define IGNORE_STDIO_STUBS +# include +# define O_NONBLOCK FNONBIO +# include +# include "palmFunctions.h" +# elif defined(SYMBIAN) +# define WITH_LEAN +# define WITH_NONAMESPACES +# define HAVE_STRTOD /* use STRTOD since sscanf doesn't seem to work */ +# include +# include +# elif defined(VXWORKS) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_PGMTIME_R +# define HAVE_PLOCALTIME_R +# define HAVE_MKTIME +# elif defined(OS390) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MB +# else +/* Default asumptions on supported functions */ +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GETHOSTBYNAME_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# endif +#endif + +/* QNX does not have a working version of strtof */ +#if defined(__QNX__) || defined(QNX) +# undef HAVE_STRTOF +#endif + +#ifndef SOAP_LONG_FORMAT +# define SOAP_LONG_FORMAT "%lld" /* printf format for 64 bit ints */ +#endif + +#ifndef SOAP_ULONG_FORMAT +# define SOAP_ULONG_FORMAT "%llu" /* printf format for unsigned 64 bit ints */ +#endif + +#ifndef WITH_NOSTDLIB +# include +# ifndef PALM +# include +# include +# endif +# include +# include +#endif + +#if defined(__cplusplus) && !defined(WITH_LEAN) +# include +# include +#endif + +#ifdef WITH_NOHTTP +# ifndef WITH_NOIO +# define WITH_NOIO +# undef WITH_COOKIES +# endif +#endif + +#ifndef UNDER_CE +# ifndef PALM +# ifndef WITH_NOIO +# include +# include +# endif +# ifndef WITH_LEAN +# ifdef HAVE_SYS_TIMEB_H +# include /* for ftime() */ +# endif +# include +# endif +# endif +#endif + +#ifdef OPENSERVER +# include +# include +# include + extern int h_errno; +#endif + +#ifndef WITH_NOIO +# ifndef WIN32 +# ifndef PALM +# include +# ifdef VXWORKS +# include +# include +# endif +# ifndef VXWORKS +# ifndef SYMBIAN +# include +# endif +# endif +# ifdef SUN_OS +# include /* SUN */ +# include /* SUN < 2.8 (?) */ +# endif +# ifdef VXWORKS +# ifdef _WRS_KERNEL +# include +# endif +# else +# include +# endif +# include +# ifdef OS390 +# include +# else +# include /* TCP_NODELAY */ +# endif +# include +# endif +# endif +#endif + +#ifdef WITH_FASTCGI +# include +#endif + +#ifdef WITH_OPENSSL +# define OPENSSL_NO_KRB5 +# include +# include +# include +# ifndef ALLOW_OLD_VERSIONS +# if (OPENSSL_VERSION_NUMBER < 0x00905100L) +# error "Must use OpenSSL 0.9.6 or later" +# endif +# endif +#endif + +#ifdef WITH_GZIP +# ifndef WITH_ZLIB +# define WITH_ZLIB +# endif +#endif + +#ifdef WITH_CASEINSENSITIVETAGS +# define SOAP_STRCMP soap_tag_cmp /* case insensitve XML element/attribute names */ +#else +# define SOAP_STRCMP strcmp /* case sensitive XML element/attribute names */ +#endif + +#ifdef WITH_ZLIB +# include +#endif + +#ifndef WITH_NOSTDLIB +# ifndef PALM +# include /* for isnan() */ +# endif +#endif + +/* #define DEBUG */ /* Uncomment to debug sending (in file SENT.log) receiving (in file RECV.log) and messages (in file TEST.log) */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef WIN32 +# ifndef UNDER_CE +# include +# include +# endif +# include +/* # include */ /* Alternative: use winsock2 (not available with eVC) */ +# ifdef WITH_IPV6 +# include +# include +# endif +#else +# ifdef VXWORKS +# include +# include +# include +# endif +# ifndef WITH_NOIO +# ifndef PALM +# include +# include +# include +# include +# endif +# endif +#endif + +/* Portability: define SOAP_SOCKLEN_T */ +#if defined(SOCKLEN_T) +# define SOAP_SOCKLEN_T SOCKLEN_T +#elif defined(__socklen_t_defined) || defined(_SOCKLEN_T) || defined(CYGWIN) || defined(FREEBSD) || defined(__FreeBSD__) || defined(__QNX__) || defined(QNX) || defined(_AIX) +# define SOAP_SOCKLEN_T socklen_t +#elif defined(IRIX) || defined(WIN32) || defined(__APPLE__) || defined(HP_UX) || defined(SUN_OS) || defined(OPENSERVER) || defined(TRU64) || defined(VXWORKS) +# define SOAP_SOCKLEN_T int +#else +# define SOAP_SOCKLEN_T size_t +#endif + +#ifdef WIN32 +# define SOAP_SOCKET SOCKET +#else +# define SOAP_SOCKET int +# define closesocket(n) close(n) +#endif + +#define SOAP_INVALID_SOCKET (-1) +#define soap_valid_socket(n) ((n) != SOAP_INVALID_SOCKET) + +#if defined(SYMBIAN) +# define LONG64 long +# define ULONG64 unsigned LONG64 +#elif !defined(WIN32) || defined(__GLIBC__) || defined(__GNU__) +# ifndef LONG64 +# define LONG64 long long +# define ULONG64 unsigned LONG64 +# endif +#elif defined(UNDER_CE) +# define LONG64 __int64 +# define ULONG64 unsigned LONG64 +#elif defined(__BORLANDC__) +# define LONG64 __int64 +# define ULONG64 unsigned LONG64 +#endif + +#if defined(WIN32) +# define soap_int32 __int32 +#elif defined(SYMBIAN) +# define soap_int32 long +#elif defined(PALM) +# define soap_int32 Int32 +#else +# define soap_int32 int32_t +#endif + +#ifdef WIN32 +# define SOAP_ERANGE ERANGE +# define SOAP_EINTR WSAEINTR +# define SOAP_EAGAIN WSAEWOULDBLOCK +# define SOAP_EWOULDBLOCK WSAEWOULDBLOCK +# define SOAP_EINPROGRESS WSAEINPROGRESS +#else +# define SOAP_ERANGE ERANGE +# define SOAP_EINTR EINTR +# define SOAP_EAGAIN EAGAIN +# ifdef SYMBIAN +# define SOAP_EWOULDBLOCK 9898 +# define SOAP_EINPROGRESS 9899 +# else +# define SOAP_EWOULDBLOCK EWOULDBLOCK +# define SOAP_EINPROGRESS EINPROGRESS +# endif +#endif + +#ifdef WIN32 +# ifdef UNDER_CE +# define soap_errno GetLastError() +# define soap_socket_errno GetLastError() +# else +# define soap_errno GetLastError() +# define soap_socket_errno WSAGetLastError() +# endif +#else +# ifndef WITH_NOIO +# define soap_errno errno +# define soap_socket_errno errno +# else +# define soap_errno 0 +# define soap_socket_errno 0 +# endif +#endif + +#ifndef SOAP_BUFLEN +# ifdef WITH_UDP +# define SOAP_BUFLEN (65536) /* max UDP packet size */ +# else +# ifndef WITH_LEAN +# define SOAP_BUFLEN (65536) /* buffer length for socket packets, also used by gethostbyname_r so don't make this too small */ +# else +# define SOAP_BUFLEN (2048) +# endif +# endif +#endif +#ifndef SOAP_LABLEN +# define SOAP_LABLEN (64) /* initial look-aside buffer length */ +#endif +#ifndef SOAP_PTRBLK +# define SOAP_PTRBLK (32) /* block allocation for pointer hash table chains */ +#endif +#ifndef SOAP_PTRHASH +# ifndef WITH_LEAN +# define SOAP_PTRHASH (1024) /* size of pointer analysis hash table (must be power of 2) */ +# else +# define SOAP_PTRHASH (32) +# endif +#endif +#ifndef SOAP_IDHASH +# ifndef WITH_LEAN +# define SOAP_IDHASH (1999) /* prime size of hash table for parsed id/ref */ +# else +# define SOAP_IDHASH (19) /* 19, 199 */ +# endif +#endif +#ifndef SOAP_BLKLEN +# ifndef WITH_LEAN +# define SOAP_BLKLEN (256) /* size of blocks to collect long strings and XML attributes */ +# else +# define SOAP_BLKLEN (32) +# endif +#endif +#ifndef SOAP_TAGLEN +# ifndef WITH_LEAN +# define SOAP_TAGLEN (256) /* maximum length of XML element tag/attribute name or host/path name + 1 */ +# else +# define SOAP_TAGLEN (64) +# endif +#endif +#ifndef SOAP_HDRLEN +# ifndef WITH_LEAN +# define SOAP_HDRLEN (8192) /* maximum length of HTTP header line (must be >4096 to read cookies) */ +# else +# define SOAP_HDRLEN (1024) +# endif +#endif +#ifndef SOAP_MAXDIMS +# ifndef WITH_LEAN +# define SOAP_MAXDIMS (16) /* maximum array dimensions (array nestings) must be less than 64 to protect soap->tmpbuf */ +# else +# define SOAP_MAXDIMS (4) +# endif +#endif + +#ifndef SOAP_MAXLOGS +# define SOAP_MAXLOGS (3) /* max number of debug logs per struct soap environment */ +# define SOAP_INDEX_RECV (0) +# define SOAP_INDEX_SENT (1) +# define SOAP_INDEX_TEST (2) +#endif + +#ifndef SOAP_MAXKEEPALIVE +# define SOAP_MAXKEEPALIVE (100) /* max iterations to keep server connection alive */ +#endif + +#ifndef SOAP_MAXARRAYSIZE +# define SOAP_MAXARRAYSIZE (100000) /* "trusted" max size of inbound SOAP array for compound array allocation */ +#endif + +#ifdef VXWORKS +# ifdef __INCmathh +# include +# ifndef HAVE_ISNAN +# define HAVE_ISNAN +# endif +# define soap_isnan(num) isNan(num) +# endif +#endif + +#ifdef WIN32 +# include +# ifndef HAVE_ISNAN +# define HAVE_ISNAN +# endif +# define soap_isnan(num) _isnan(num) +#endif + +#ifdef SUN_OS +# define soap_isnan(n) isnan(n) +#endif + +#if !defined(HAVE_ISNAN) && (defined(_MATH_H) || defined(_MATH_INCLUDED)) +# define HAVE_ISNAN +#endif + +#ifndef soap_isnan +# ifdef HAVE_ISNAN +# define soap_isnan(n) isnan(n) +# else +# define soap_isnan(_) (0) +# endif +#endif + +extern const struct soap_double_nan { unsigned int n1, n2; } soap_double_nan; + +#ifdef VXWORKS +# ifndef FLT_MAX +# define FLT_MAX _ARCH_FLT_MAX +# endif +# ifndef DBL_MAX +# define DBL_MAX _ARCH_DBL_MAX +# endif +#endif + +#ifndef FLT_NAN +# ifdef HAVE_ISNAN +# define FLT_NAN (*(float*)(void*)&soap_double_nan) +# else +# define FLT_NAN (0.0) +# endif +#endif + +#ifndef FLT_PINFTY +# if defined(FLT_MAX) +# define FLT_PINFTY FLT_MAX +# elif defined(HUGE_VALF) +# define FLT_PINFTY (float)HUGE_VALF +# elif defined(HUGE_VAL) +# define FLT_PINFTY (float)HUGE_VAL +# elif defined(FLOAT_MAX) +# define FLT_PINFTY FLOAT_MAX +# else +# define FLT_PINFTY (3.40282347e+38F) +# endif +#endif + +#ifndef FLT_NINFTY +# define FLT_NINFTY (-FLT_PINFTY) +#endif + +#ifndef DBL_NAN +# ifdef HAVE_ISNAN +# define DBL_NAN (*(double*)(void*)&soap_double_nan) +# else +# define DBL_NAN (0.0) +# endif +#endif + +#ifndef DBL_PINFTY +# if defined(DBL_MAX) +# define DBL_PINFTY DBL_MAX +# elif defined(HUGE_VALF) +# define DBL_PINFTY (double)HUGE_VALF +# elif defined(HUGE_VAL) +# define DBL_PINFTY (double)HUGE_VAL +# elif defined(DOUBLE_MAX) +# define DBL_PINFTY DOUBLE_MAX +# else +# define DBL_PINFTY (1.7976931348623157e+308) +# endif +#endif + +#ifndef DBL_NINFTY +# define DBL_NINFTY (-DBL_PINFTY) +#endif + +#define soap_ispinfd(n) ((n) >= DBL_PINFTY) +#define soap_ispinff(n) ((n) >= FLT_PINFTY) +#define soap_isninfd(n) ((n) <= DBL_NINFTY) +#define soap_isninff(n) ((n) <= FLT_NINFTY) + +/* gSOAP error codes */ + +#define SOAP_EOF EOF +#define SOAP_ERR EOF +#define SOAP_OK 0 +#define SOAP_CLI_FAULT 1 +#define SOAP_SVR_FAULT 2 +#define SOAP_TAG_MISMATCH 3 +#define SOAP_TYPE 4 +#define SOAP_SYNTAX_ERROR 5 +#define SOAP_NO_TAG 6 +#define SOAP_IOB 7 +#define SOAP_MUSTUNDERSTAND 8 +#define SOAP_NAMESPACE 9 +#define SOAP_USER_ERROR 10 +#define SOAP_FATAL_ERROR 11 +#define SOAP_FAULT 12 +#define SOAP_NO_METHOD 13 +#define SOAP_GET_METHOD 14 +#define SOAP_EOM 15 +#define SOAP_NULL 16 +#define SOAP_DUPLICATE_ID 17 +#define SOAP_MISSING_ID 18 +#define SOAP_HREF 19 +#define SOAP_UDP_ERROR 20 +#define SOAP_TCP_ERROR 21 +#define SOAP_HTTP_ERROR 22 +#define SOAP_SSL_ERROR 23 +#define SOAP_ZLIB_ERROR 24 +#define SOAP_DIME_ERROR 25 +#define SOAP_DIME_HREF 26 +#define SOAP_DIME_MISMATCH 27 +#define SOAP_DIME_END 28 +#define SOAP_MIME_ERROR 29 +#define SOAP_MIME_HREF 30 +#define SOAP_MIME_END 31 +#define SOAP_VERSIONMISMATCH 32 +#define SOAP_PLUGIN_ERROR 33 +#define SOAP_DATAENCODINGUNKNOWN 34 +#define SOAP_REQUIRED 35 +#define SOAP_PROHIBITED 36 +#define SOAP_OCCURS 37 +#define SOAP_LENGTH 38 + +#define soap_xml_error_check(e) ((e) == SOAP_TAG_MISMATCH || (e) == SOAP_TAG_END || (e) == SOAP_SYNTAX_ERROR || (e) == SOAP_NAMESPACE || (e) == SOAP_DUPLICATE_ID || (e) == SOAP_MISSING_ID || (e) == SOAP_REQUIRED || (e) == SOAP_PROHIBITED || (e) == SOAP_OCCURS || (e) == SOAP_LENGTH || (e) == SOAP_NULL || (e) == SOAP_HREF) +#define soap_soap_error_check(e) ((e) == SOAP_CLI_FAULT || (e) == SOAP_SVR_FAULT || (e) == SOAP_VERSIONMISMATCH || (e) == SOAP_MUSTUNDERSTAND || (e) == SOAP_FAULT || (e) == SOAP_NO_METHOD) +#define soap_tcp_error_check(e) ((e) == SOAP_EOF || (e) == SOAP_TCP_ERROR) +#define soap_ssl_error_check(e) ((e) == SOAP_SSL_ERROR) +#define soap_zlib_error_check(e) ((e) == SOAP_ZLIB_ERROR) +#define soap_http_error_check(e) ((e) == SOAP_HTTP_ERROR || (e) == SOAP_GET_METHOD || ((e) >= 100 && (e) < 600)) + +/* gSOAP HTTP response status codes 100 to 599 are reserved */ + +/* Codes 600 to 999 are user definable */ + +/* Exceptional gSOAP HTTP response status codes >= 1000 */ + +#define SOAP_STOP 1000 /* No HTTP response */ +#define SOAP_FORM 1001 /* Form request/response */ +#define SOAP_HTML 1002 /* Custom HTML response */ +#define SOAP_FILE 1003 /* Custom file-based response */ + +/* gSOAP HTTP method codes */ + +#define SOAP_POST 2000 +#define SOAP_GET 2001 + +/* gSOAP DIME */ + +#define SOAP_DIME_CF 0x01 +#define SOAP_DIME_ME 0x02 +#define SOAP_DIME_MB 0x04 +#define SOAP_DIME_VERSION 0x08 /* DIME version 1 */ +#define SOAP_DIME_MEDIA 0x10 +#define SOAP_DIME_ABSURI 0x20 + +/* gSOAP ZLIB */ + +#define SOAP_ZLIB_NONE 0x00 +#define SOAP_ZLIB_DEFLATE 0x01 +#define SOAP_ZLIB_INFLATE 0x02 +#define SOAP_ZLIB_GZIP 0x02 + +/* gSOAP transport, connection, and content encoding modes */ + +typedef soap_int32 soap_mode; + +#define SOAP_IO 0x00000003 /* IO mask */ +#define SOAP_IO_FLUSH 0x00000000 /* flush output immediately, no buffering */ +#define SOAP_IO_BUFFER 0x00000001 /* buffer output in packets of size SOAP_BUFLEN */ +#define SOAP_IO_STORE 0x00000002 /* store entire output to determine length for transport */ +#define SOAP_IO_CHUNK 0x00000003 /* use HTTP chunked transfer AND buffer packets */ + +#define SOAP_IO_UDP 0x00000004 +#define SOAP_IO_LENGTH 0x00000008 +#define SOAP_IO_KEEPALIVE 0x00000010 + +#define SOAP_ENC_LATIN 0x00800020 /* iso-8859-1 encoding */ +#define SOAP_ENC_XML 0x00000040 /* plain XML encoding, no HTTP header */ +#define SOAP_ENC_DIME 0x00000080 +#define SOAP_ENC_MIME 0x00000100 +#define SOAP_ENC_MTOM 0x00000200 +#define SOAP_ENC_ZLIB 0x00000400 +#define SOAP_ENC_SSL 0x00000800 + +#define SOAP_ENC 0x00000FFF /* IO and ENC mask */ + +#define SOAP_XML_STRICT 0x00001000 /* strict validation */ +#define SOAP_XML_INDENT 0x00002000 +#define SOAP_XML_CANONICAL 0x00004000 /* EXC C14N canonical XML */ +#define SOAP_XML_TREE 0x00008000 +#define SOAP_XML_GRAPH 0x00010000 +#define SOAP_XML_NIL 0x00020000 +#define SOAP_XML_DOM 0x00040000 +#define SOAP_XML_SEC 0x00080000 /* reserved for WS security */ + +#define SOAP_C_NOIOB 0x00100000 +#define SOAP_C_UTFSTRING 0x00200000 +#define SOAP_C_MBSTRING 0x00400000 + +#define SOAP_DOM_TREE 0x01000000 +#define SOAP_DOM_NODE 0x02000000 +#define SOAP_DOM_ASIS 0x04000000 + +#define SOAP_IO_DEFAULT SOAP_IO_FLUSH + +/* SSL client/server authentication settings */ + +#define SOAP_SSL_NO_AUTHENTICATION 0x00 /* for testing purposes */ +#define SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION 0x01 /* client requires server to authenticate */ +#define SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION 0x02 /* server requires client to authenticate */ + +#define SOAP_SSL_DEFAULT SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION + +/* */ + +#define SOAP_BEGIN 0 +#define SOAP_IN_ENVELOPE 2 +#define SOAP_IN_HEADER 3 +#define SOAP_END_HEADER 4 +#define SOAP_NO_BODY 5 +#define SOAP_IN_BODY 6 +#define SOAP_END_BODY 7 +#define SOAP_END_ENVELOPE 8 +#define SOAP_END 9 +#define SOAP_BEGIN_SECURITY 10 +#define SOAP_IN_SECURITY 11 +#define SOAP_END_SECURITY 12 + +/* DEBUG macros */ + +#ifndef WITH_LEAN +# ifdef DEBUG +# ifndef SOAP_DEBUG +# define SOAP_DEBUG +# endif +# endif +#endif + +#ifdef SOAP_DEBUG +# define SOAP_MALLOC(soap, size) soap_track_malloc(soap, __FILE__, __LINE__, size) +# define SOAP_FREE(soap, ptr) soap_track_free(soap, __FILE__, __LINE__, ptr) +#endif + +#ifndef SOAP_MALLOC /* use libc malloc */ +# define SOAP_MALLOC(soap, size) malloc(size) +#endif + +#ifndef SOAP_FREE /* use libc free */ +# define SOAP_FREE(soap, ptr) free(ptr) +#endif + +#ifdef SOAP_DEBUG +# ifndef SOAP_MESSAGE +# define SOAP_MESSAGE fprintf +# endif +# ifndef DBGLOG +# define DBGLOG(DBGFILE, CMD) \ +{ if (soap)\ + { if (!soap->fdebug[SOAP_INDEX_##DBGFILE])\ + soap_open_logfile(soap, SOAP_INDEX_##DBGFILE);\ + if (soap->fdebug[SOAP_INDEX_##DBGFILE])\ + { FILE *fdebug = soap->fdebug[SOAP_INDEX_##DBGFILE];\ + CMD;\ + fflush(fdebug);\ + }\ + }\ +} +# endif +# ifndef DBGMSG +# define DBGMSG(DBGFILE, MSG, LEN) \ +{ if (soap)\ + { if (!soap->fdebug[SOAP_INDEX_##DBGFILE])\ + soap_open_logfile(soap, SOAP_INDEX_##DBGFILE);\ + if (soap->fdebug[SOAP_INDEX_##DBGFILE])\ + { fwrite((MSG), 1, (LEN), soap->fdebug[SOAP_INDEX_##DBGFILE]);\ + fflush(soap->fdebug[SOAP_INDEX_##DBGFILE]);\ + }\ + }\ +} +# endif +# ifndef DGBFUN +# define DBGFUN(FNAME) DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): %s()\n", __FILE__, __LINE__, FNAME)) +# define DBGFUN1(FNAME, FMT, ARG) DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): %s("FMT")\n", __FILE__, __LINE__, FNAME, (ARG))) +# define DBGFUN2(FNAME, FMT1, ARG1, FMT2, ARG2) DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): %s("FMT1", "FMT2")\n", __FILE__, __LINE__, FNAME, (ARG1), (ARG2))) +# define DBGFUN3(FNAME, FMT1, ARG1, FMT2, ARG2, FMT3, ARG3) DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): %s("FMT1", "FMT2", "FMT3")\n", __FILE__, __LINE__, FNAME, (ARG1), (ARG2), (ARG3))) +# endif +# ifndef DBGHEX +# define DBGHEX(DBGFILE, MSG, LEN) \ +{ if (soap)\ + { if (!soap->fdebug[SOAP_INDEX_##DBGFILE])\ + soap_open_logfile(soap, SOAP_INDEX_##DBGFILE);\ + if (soap->fdebug[SOAP_INDEX_##DBGFILE])\ + { int i; char *s;\ + for (s = (char*)(MSG), i = (LEN); i; i--)\ + fprintf(soap->fdebug[SOAP_INDEX_##DBGFILE], "%2.2hhX ", *s++);\ + fflush(soap->fdebug[SOAP_INDEX_##DBGFILE]);\ + }\ + }\ +} +# endif +#else +# define DBGLOG(DBGFILE, CMD) +# define DBGMSG(DBGFILE, MSG, LEN) +# define DBGFUN(FNAME) +# define DBGFUN1(FNAME, FMT, ARG) +# define DBGFUN2(FNAME, FMT1, ARG1, FMT2, ARG2) +# define DBGFUN3(FNAME, FMT1, ARG1, FMT2, ARG2, FMT3, ARG3) +# define DBGHEX(DBGFILE, MSG, LEN) +#endif + +/* UCS-4 requires 32 bits (0-7FFFFFFF, the sign bit is used by gSOAP to distinguish XML entities) */ +typedef soap_int32 soap_wchar; + +/* namespace table row */ +struct Namespace +{ const char *id; + const char *ns; + const char *in; + char *out; +}; + +/* namespace stack */ +struct soap_nlist +{ struct soap_nlist *next; + unsigned int level; /* nesting depth level */ + short index; /* corresponding entry in ns mapping table */ + char *ns; /* only set when parsed ns URI is not in the ns mapping table */ + char id[1]; /* the actual string value flows into the allocated region below this struct */ +}; + +/* block stack for nested block allocations */ +struct soap_blist +{ struct soap_blist *next; + char *ptr; + size_t size; +}; + +/* array layout */ +struct soap_array +{ void *__ptr; + int __size; +}; + +/* pointer serialization management */ +struct soap_plist +{ struct soap_plist *next; + const void *ptr; + const struct soap_array *array; + int type; + int id; + char mark1; + char mark2; +}; + +/* block allocation for pointer serialization management */ +struct soap_pblk +{ struct soap_pblk *next; + struct soap_plist plist[SOAP_PTRBLK]; +}; + +#ifdef SOAP_DEBUG +/* malloc/free tracking for debugging */ +struct soap_mlist +{ struct soap_mlist *next; + const void *ptr; + const char *file; + int line; + short live; +}; +#endif + +/* class allocation list */ +struct soap_clist +{ struct soap_clist *next; + void *ptr; + int type; + int size; + void (*fdelete)(struct soap_clist*); +}; + +/* attributes */ +struct soap_attribute +{ struct soap_attribute *next; + char *value; + size_t size; + char *ns; + short visible; + char name[1]; /* the actual name string flows into the allocated region below this struct */ +}; + +struct soap_cookie +{ struct soap_cookie *next; + char *name; + char *value; + char *domain; + char *path; + long expire; /* client-side: local time to expire; server-side: seconds to expire */ + unsigned int version; + short secure; + short session; /* server-side */ + short env; /* server-side: got cookie from client and should not be (re)send */ + short modified; /* server-side: client cookie was modified and should be send */ +}; + +#ifdef __cplusplus +SOAP_FMAC1 struct soap_multipart* SOAP_FMAC2 soap_next_multipart(struct soap_multipart*); + +class soap_multipart_iterator +{ public: + struct soap_multipart *content; + bool operator==(const soap_multipart_iterator& iter) const + { return content == iter.content; } + bool operator!=(const soap_multipart_iterator& iter) const + { return content != iter.content; } + struct soap_multipart &operator*() const + { return *content; } + soap_multipart_iterator &operator++() + { content = soap_next_multipart(content); return *this; } + soap_multipart_iterator() : content(NULL) + { } + soap_multipart_iterator(struct soap_multipart *p) : content(p) + { } +}; +#endif + +#ifndef WITH_LEANER +struct soap_dime +{ size_t count; + size_t size; + size_t chunksize; + size_t buflen; + char flags; + char *ptr; + const char *id; + const char *type; + const char *options; + struct soap_multipart *list; /* list of DIME attachments received */ + struct soap_multipart *first, *last; /* temporary in/out queue */ +#ifdef __cplusplus + soap_multipart_iterator begin() + { soap_multipart_iterator iter(list); return iter; }; + soap_multipart_iterator end() + { soap_multipart_iterator iter(NULL); return iter; }; +#endif +}; +#endif + +#ifndef WITH_LEANER +struct soap_mime +{ char *boundary; /* MIME boundary */ + const char *start; /* MIME start ID */ + struct soap_multipart *list; /* list of MIME attachments received */ + struct soap_multipart *first, *last; /* temporary in/out queue */ +#ifdef __cplusplus + soap_multipart_iterator begin() + { soap_multipart_iterator iter(list); return iter; }; + soap_multipart_iterator end() + { soap_multipart_iterator iter(NULL); return iter; }; +#endif +}; +#endif + +#ifndef WITH_LEANER +/* RFC2045 MIME content transfer encodings */ +enum soap_mime_encoding +{ SOAP_MIME_NONE, + SOAP_MIME_7BIT, + SOAP_MIME_8BIT, + SOAP_MIME_BINARY, + SOAP_MIME_QUOTED_PRINTABLE, + SOAP_MIME_BASE64, + SOAP_MIME_IETF_TOKEN, + SOAP_MIME_X_TOKEN +}; +#endif + +#ifndef WITH_LEANER +/* DIME/MIME multipart list */ +struct soap_multipart +{ struct soap_multipart *next; + char *ptr; /* points to raw data content */ + size_t size; /* size of data content */ + const char *id; /* DIME/MIME content ID or form data name */ + const char *type; /* DIME/MIME type (MIME type format) */ + const char *options; /* DIME options */ + enum soap_mime_encoding encoding; /* MIME Content-Transfer-Encoding */ + const char *location; /* MIME Content-Location (optional) */ + const char *description; /* MIME Content-Description (optional) */ +#ifdef __cplusplus + typedef soap_multipart_iterator iterator; +#endif +}; +#endif + +#ifndef WITH_LEANER +/* attachment DIME and MTOM XOP forwarding */ +struct soap_xlist +{ struct soap_xlist *next; + unsigned char **ptr; + int *size; + char *id; + char **type; + char **options; +}; +#endif + +/******************************************************************************/ + +#ifndef WITH_LEANER +#ifdef __cplusplus +class soap_dom_attribute_iterator +{ public: + struct soap_dom_attribute *att; + const char *nstr; + const char *name; + bool operator==(const soap_dom_attribute_iterator&) const; + bool operator!=(const soap_dom_attribute_iterator&) const; + struct soap_dom_attribute &operator*() const; + soap_dom_attribute_iterator &operator++(); + soap_dom_attribute_iterator(); + soap_dom_attribute_iterator(struct soap_dom_attribute*); + ~soap_dom_attribute_iterator(); +}; +#endif +#endif + +#ifndef WITH_LEANER +struct soap_dom_attribute +{ struct soap_dom_attribute *next; + const char *nstr; + char *name; + char *data; + wchar_t *wide; + struct soap *soap; +#ifdef __cplusplus + typedef soap_dom_attribute_iterator iterator; + struct soap_dom_attribute &set(const char *nstr, const char *name); /* set namespace and name */ + struct soap_dom_attribute &set(const char *data); /* set data */ + soap_dom_attribute_iterator begin(); + soap_dom_attribute_iterator end(); + soap_dom_attribute_iterator find(const char *nstr, const char *name); + void unlink(); + soap_dom_attribute(); + soap_dom_attribute(struct soap *soap); + soap_dom_attribute(struct soap *soap, const char *nstr, const char *name, const char *data); + ~soap_dom_attribute(); +#endif +}; +#endif + +#ifndef WITH_LEANER +#ifdef __cplusplus +class soap_dom_element_iterator +{ public: + struct soap_dom_element *elt; + const char *nstr; + const char *name; + int type; + bool operator==(const soap_dom_element_iterator&) const; + bool operator!=(const soap_dom_element_iterator&) const; + struct soap_dom_element &operator*() const; + soap_dom_element_iterator &operator++(); + soap_dom_element_iterator(); + soap_dom_element_iterator(struct soap_dom_element*); + ~soap_dom_element_iterator(); +}; +#endif +#endif + +#ifndef WITH_LEANER +struct soap_dom_element +{ struct soap_dom_element *next; /* next sibling */ + struct soap_dom_element *prnt; /* parent */ + struct soap_dom_element *elts; /* list of child elements */ + struct soap_dom_attribute *atts; /* list of attributes */ + const char *nstr; /* namespace string */ + char *name; /* element tag name */ + char *data; /* element content data (with SOAP_C_UTFSTRING flag set) */ + wchar_t *wide; /* element content data */ + int type; /* optional: serialized C/C++ data type */ + void *node; /* optional: pointer to serialized C/C++ data */ + char *head; /* leading whitespace to start tag */ + char *tail; /* leading whitespace to end tag */ + struct soap *soap; /* soap context that manages this node */ +#ifdef __cplusplus + typedef soap_dom_element_iterator iterator; + struct soap_dom_element &set(const char *nstr, const char *name); + struct soap_dom_element &set(const char *data); + struct soap_dom_element &set(void *node, int type); + struct soap_dom_element &add(struct soap_dom_element*); + struct soap_dom_element &add(struct soap_dom_element&); + struct soap_dom_element &add(struct soap_dom_attribute*); + struct soap_dom_element &add(struct soap_dom_attribute&); + soap_dom_element_iterator begin(); + soap_dom_element_iterator end(); + soap_dom_element_iterator find(const char *nstr, const char *name); + soap_dom_element_iterator find(int type); + void unlink(); + soap_dom_element(); + soap_dom_element(struct soap *soap); + soap_dom_element(struct soap *soap, const char *nstr, const char *name); + soap_dom_element(struct soap *soap, const char *nstr, const char *name, const char *data); + soap_dom_element(struct soap *soap, const char *nstr, const char *name, void *node, int type); + ~soap_dom_element(); +#endif +}; +SOAP_FMAC1 const char* SOAP_FMAC2 soap_dom_current_nstr(struct soap *soap, const char *tag); +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_dom_next_element(struct soap_dom_element *elt); +SOAP_FMAC1 struct soap_dom_attribute * SOAP_FMAC2 soap_dom_next_attribute(struct soap_dom_attribute *att); +#endif + +#if defined(__cplusplus) && !defined(WITH_LEAN) +} +extern std::ostream &operator<<(std::ostream&, const struct soap_dom_element&); +extern std::istream &operator>>(std::istream&, struct soap_dom_element&); +extern "C" { +#endif + +/******************************************************************************/ + +struct soap +{ short version; /* 1 = SOAP1.1 and 2 = SOAP1.2 (set automatically from namespace URI in nsmap table) */ + short copy; /* 1 = copy of another soap struct */ + soap_mode mode; + soap_mode imode; + soap_mode omode; + const char *float_format; /* user-definable format string for floats (<1024 chars) */ + const char *double_format; /* user-definable format string for doubles (<1024 chars) */ + const char *dime_id_format; /* user-definable format string for integer DIME id ( 0, gives socket recv timeout in seconds, < 0 in usec */ + int send_timeout; /* when > 0, gives socket send timeout in seconds, < 0 in usec */ + int connect_timeout; /* when > 0, gives socket connect() timeout in seconds, < 0 in usec */ + int accept_timeout; /* when > 0, gives socket accept() timeout in seconds, < 0 in usec */ + int socket_flags; /* socket recv() and send() flags, e.g. set to MSG_NOSIGNAL to disable sigpipe */ + int connect_flags; /* connect() SOL_SOCKET sockopt flags, e.g. set to SO_DEBUG to debug socket */ + int bind_flags; /* bind() SOL_SOCKET sockopt flags, e.g. set to SO_REUSEADDR to enable reuse */ + int accept_flags; /* accept() SOL_SOCKET sockopt flags */ + const struct Namespace *namespaces; /* Pointer to global namespace mapping table */ + struct Namespace *local_namespaces; /* Local namespace mapping table */ + struct soap_nlist *nlist; /* namespace stack */ + struct soap_blist *blist; /* block allocation stack */ + struct soap_clist *clist; /* class instance allocation list */ + void *alist; /* memory allocation (malloc) list */ + struct soap_ilist *iht[SOAP_IDHASH]; + struct soap_plist *pht[SOAP_PTRHASH]; + struct soap_pblk *pblk; /* plist block allocation */ + short pidx; /* plist block allocation */ + struct SOAP_ENV__Header *header; + struct SOAP_ENV__Fault *fault; + int idnum; + void *user; /* to pass user-defined data */ + struct soap_plugin *plugins; /* linked list of plug-in data */ + char *userid; /* HTTP Basic authorization userid */ + char *passwd; /* HTTP Basic authorization passwd */ + int (*fpost)(struct soap*, const char*, const char*, int, const char*, const char*, size_t); + int (*fget)(struct soap*); + int (*fform)(struct soap*); + int (*fposthdr)(struct soap*, const char*, const char*); + int (*fresponse)(struct soap*, int, size_t); + int (*fparse)(struct soap*); + int (*fparsehdr)(struct soap*, const char*, const char*); + int (*fresolve)(struct soap*, const char*, struct in_addr* inaddr); + int (*fconnect)(struct soap*, const char*, const char*, int); + int (*fdisconnect)(struct soap*); + int (*fclosesocket)(struct soap*, SOAP_SOCKET); + int (*fshutdownsocket)(struct soap*, SOAP_SOCKET, int); + int (*fopen)(struct soap*, const char*, const char*, int); + int (*faccept)(struct soap*, int, struct sockaddr*, int *n); + int (*fclose)(struct soap*); + int (*fsend)(struct soap*, const char*, size_t); + size_t (*frecv)(struct soap*, char*, size_t); + int (*fpoll)(struct soap*); + void (*fseterror)(struct soap*, const char **c, const char **s); + int (*fignore)(struct soap*, const char*); + int (*fserveloop)(struct soap*); + void *(*fplugin)(struct soap*, const char*); +#ifndef WITH_LEANER + int (*fprepareinit)(struct soap*); + int (*fpreparesend)(struct soap*, const char*, size_t); + int (*fpreparerecv)(struct soap*, const char*, size_t); + int (*fpreparefinal)(struct soap*); + void *(*fdimereadopen)(struct soap*, void*, const char*, const char*, const char*); + void *(*fdimewriteopen)(struct soap*, const char*, const char*, const char*); + void (*fdimereadclose)(struct soap*, void*); + void (*fdimewriteclose)(struct soap*, void*); + size_t (*fdimeread)(struct soap*, void*, char*, size_t); + int (*fdimewrite)(struct soap*, void*, const char*, size_t); +#endif + int master; + int socket; +#if defined(__cplusplus) && !defined(WITH_LEAN) + std::ostream *os; + std::istream *is; +#else + void *os; /* preserve alignment */ + void *is; /* preserve alignment */ +#endif +#ifndef UNDER_CE + int sendfd; + int recvfd; +#else + FILE *sendfd; + FILE *recvfd; +#endif +#ifdef WIN32 + char errorstr[256]; /* buf for FormatMessage() */ +#endif + size_t bufidx; /* index in soap.buf[] */ + size_t buflen; /* length of soap.buf[] content */ + soap_wchar ahead; /* parser lookahead */ + short cdata; /* CDATA parser state */ + short body; /* parsed XML element has a body or not */ + unsigned int level; /* XML nesting level */ + size_t count; /* message length counter */ + size_t length; /* message length as set by HTTP header */ +#ifdef WITH_FAST + char *labbuf; /* look-aside buffer */ + size_t lablen; /* look-aside buffer allocated length */ + size_t labidx; /* look-aside buffer index to available part */ +#endif + char buf[SOAP_BUFLEN];/* send and receive buffer */ + char tmpbuf[1024]; /* in/output buffer for HTTP headers, simpleType values, attribute names, and DIME >=1024 bytes */ + char msgbuf[1024]; /* output buffer for (error) messages <=1024 bytes */ + char tag[SOAP_TAGLEN]; + char id[SOAP_TAGLEN]; + char href[SOAP_TAGLEN]; + char type[SOAP_TAGLEN]; + char arrayType[SOAP_TAGLEN]; + char arraySize[SOAP_TAGLEN]; + char arrayOffset[SOAP_TAGLEN]; + short other; + short position; + int positions[SOAP_MAXDIMS]; + short root; + struct soap_attribute *attributes; /* attribute list */ + short encoding; /* when set, output encodingStyle */ + short mustUnderstand; /* a mustUnderstand element was parsed or is output */ + short keep_alive; /* connection should be kept open */ + short null; /* parsed XML is xsi:nil */ + short ns; /* when not set, output full xmlns bindings */ + short part; /* parsing state */ + short alloced; + short peeked; + size_t chunksize; + size_t chunkbuflen; + char endpoint[SOAP_TAGLEN]; + char path[SOAP_TAGLEN]; + char host[SOAP_TAGLEN]; + char *action; + char *authrealm; /* HTTP authentication realm */ + char *prolog; /* XML declaration prolog */ + unsigned long ip; /* IP number */ + int port; /* port number */ + unsigned int max_keep_alive; + const char *proxy_host; /* Proxy Server host name */ + int proxy_port; /* Proxy Server port (default = 8080) */ + const char *proxy_userid; /* Proxy Authorization user name */ + const char *proxy_passwd; /* Proxy Authorization password */ + int status; /* -1 when request, else error code to be returned by server */ + int error; + int errmode; + int errnum; +#ifndef WITH_LEANER + struct soap_dom_element *dom; + struct soap_dime dime; + struct soap_mime mime; + struct soap_xlist *xlist; +#endif +#if !defined(WITH_LEAN) || defined(SOAP_DEBUG) + const char *logfile[SOAP_MAXLOGS]; + FILE *fdebug[SOAP_MAXLOGS]; + struct soap_mlist *mht[SOAP_PTRHASH]; +#endif +#ifndef WITH_LEAN + const char *c14ninclude; + const char *c14nexclude; + struct soap_cookie *cookies; + const char *cookie_domain; + const char *cookie_path; + int cookie_max; +#endif +#ifndef WITH_NOIO +#ifdef WITH_IPV6 + struct sockaddr_storage peer; /* IPv6: set by soap_accept and by UDP recv */ +#else + struct sockaddr_in peer; /* IPv4: set by soap_connect/soap_accept and by UDP recv */ +#endif + size_t peerlen; +#endif +#ifdef WITH_OPENSSL + int (*fsslauth)(struct soap*); + int (*fsslverify)(int, X509_STORE_CTX*); + BIO *bio; + SSL *ssl; + SSL_CTX *ctx; + short require_server_auth; + short require_client_auth; + short rsa; /* when set, use RSA instead of DH */ + const char *keyfile; + const char *password; + const char *dhfile; + const char *cafile; + const char *capath; + const char *crlfile; + const char *randfile; + SSL_SESSION *session; + char session_host[SOAP_TAGLEN]; + int session_port; +#endif +#ifdef WITH_ZLIB + short zlib_state; /* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_INFLATE */ + short zlib_in; /* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_GZIP */ + short zlib_out; /* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_GZIP */ + z_stream d_stream; /* decompression stream */ + char z_buf[SOAP_BUFLEN]; /* buffer */ + size_t z_buflen; + unsigned short z_level; /* compression level to be used (0=none, 1=fast to 9=best) */ + uLong z_crc; /* internal gzip crc */ + float z_ratio_in; /* detected compression ratio compressed_length/length of inbound message */ + float z_ratio_out; /* detected compression ratio compressed_length/length of outbound message */ +#endif +/* WR[ */ +#ifdef WMW_RPM_IO + void *rpmreqid; +#endif /* WMW_RPM_IO */ +/* ]WR */ +}; + +struct soap_code_map +{ long code; + const char *string; +}; + +/* forwarding list */ +struct soap_flist +{ struct soap_flist *next; + int type; + void *ptr; + unsigned int level; + void (*fcopy)(struct soap*, int, int, void*, const void*, size_t); +}; + +/* id-ref forwarding list */ +struct soap_ilist +{ struct soap_ilist *next; + int type; + size_t size; + void *link; + void *copy; + struct soap_flist *flist; + void *ptr; + unsigned int level; + char id[1]; /* the actual id string value flows into the allocated region below this struct */ +}; + +struct soap_plugin +{ struct soap_plugin *next; + const char *id; + void *data; + int (*fcopy)(struct soap *soap, struct soap_plugin *dst, struct soap_plugin *src); + void (*fdelete)(struct soap *soap, struct soap_plugin *p); /* should delete fields of plugin only and not free(p) */ +}; + +#ifndef WITH_NONAMESPACES +extern SOAP_NMAC struct Namespace namespaces[]; +#endif + +#ifndef WITH_LEAN +# define soap_get0(soap) (((soap)->bufidx>=(soap)->buflen && soap_recv(soap)) ? EOF : (unsigned char)(soap)->buf[(soap)->bufidx]) +# define soap_get1(soap) (((soap)->bufidx>=(soap)->buflen && soap_recv(soap)) ? EOF : (unsigned char)(soap)->buf[(soap)->bufidx++]) +#else +soap_wchar soap_get0(struct soap*); +soap_wchar soap_get1(struct soap*); +#endif + +#define soap_revget1(soap) ((soap)->bufidx--) +#define soap_unget(soap, c) ((soap)->ahead = c) +#define soap_register_plugin(soap, plugin) soap_register_plugin_arg(soap, plugin, NULL) +#define soap_imode(soap, n) ((soap)->mode = (soap)->imode = (n)) +#define soap_set_imode(soap, n) ((soap)->imode |= (n)) +#define soap_clr_imode(soap, n) ((soap)->imode &= ~(n)) +#define soap_omode(soap, n) ((soap)->mode = (soap)->omode = (n)) +#define soap_set_omode(soap, n) ((soap)->omode |= (n)) +#define soap_clr_omode(soap, n) ((soap)->omode &= ~(n)) +#define soap_set_mode(soap, n) ((soap)->imode |= (n), (soap)->omode |= (n)) +#define soap_clr_mode(soap, n) ((soap)->imode &= ~(n), (soap)->omode &= ~(n)) +#define soap_destroy(soap) soap_delete((soap), NULL) + +#ifdef HAVE_STRRCHR +# define soap_strrchr(s, t) strrchr(s, t) +#else + SOAP_FMAC1 char* SOAP_FMAC2 soap_strrchr(const char *s, int t); +#endif + +#ifdef HAVE_STRTOL +# define soap_strtol(s, t, b) strtol(s, t, b) +#else + SOAP_FMAC1 long SOAP_FMAC2 soap_strtol(const char *s, char **t, int b); +#endif + +#ifdef HAVE_STRTOUL +# define soap_strtoul(s, t, b) strtoul(s, t, b) +#else + SOAP_FMAC1 unsigned long SOAP_FMAC2 soap_strtoul(const char *s, char **t, int b); +#endif + +#if defined(WITH_OPENSSL) +# define soap_random soap_rand() +SOAP_FMAC1 int SOAP_FMAC2 soap_rand(); +#elif defined(HAVE_RANDOM) +# define soap_random (int)random() +#else +# define soap_random rand() +#endif + +#ifdef WITH_NOIDREF +# define soap_embedded(s, p, t) (0) +# define soap_id_lookup(s, i, p, t, n, k) (p) +# define soap_id_forward(s, h, p, st, tt, n, k, fc) (p) +# define soap_reference(s, a, t) (1) +# define soap_array_reference(s, p, a, n, t) (1) +# define soap_embed(s, p, a, n, t, pp) (0) +# define soap_embedded_id(s, i, p, t) (i) +# define soap_is_embedded(s, p) (0) +# define soap_is_single(s, p) (1) +# define soap_lookup_type(s, i) (0) +# define soap_getindependent(s) (0) +# define soap_putindependent(s) (0) +# define soap_getelement(s, n) (n) +# define soap_putelement(s, p, t, i, n) (0) +# define soap_markelement(s, p, n) (0) +#endif + +SOAP_FMAC1 void SOAP_FMAC2 soap_fault(struct soap*); +SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultcode(struct soap*); +SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultsubcode(struct soap*); +SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultstring(struct soap*); +SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultdetail(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_serializeheader(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putheader(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getheader(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_serializefault(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putfault(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getfault(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_poll(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_connect_command(struct soap*, int, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_connect(struct soap*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_bind(struct soap*, const char*, int, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_accept(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_accept(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_server_context(struct soap*, unsigned short, const char*, const char*, const char*, const char*, const char*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_client_context(struct soap*, unsigned short, const char*, const char*, const char*, const char*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_puthttphdr(struct soap*, int status, size_t count); + +SOAP_FMAC1 const char* SOAP_FMAC2 soap_get_header_attribute(struct soap*, const char*, const char*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_decode_key(char*, size_t, const char*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_decode_val(char*, size_t, const char*); + +SOAP_FMAC1 size_t SOAP_FMAC2 soap_hash(const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_endpoint(struct soap*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_flush_raw(struct soap*, const char*, size_t); +SOAP_FMAC1 int SOAP_FMAC2 soap_flush(struct soap*); +SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_get(struct soap*); +SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_getchar(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_tag_cmp(const char*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_fault(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_sender_fault(struct soap*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_sender_fault_subcode(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_receiver_fault(struct soap*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_receiver_fault_subcode(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_sender_error(struct soap*, const char*, const char*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_receiver_error(struct soap*, const char*, const char*, int); + +SOAP_FMAC1 int SOAP_FMAC2 soap_send_raw(struct soap*, const char*, size_t); +SOAP_FMAC1 int SOAP_FMAC2 soap_recv_raw(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_recv(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_send(struct soap*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_send2(struct soap*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_send3(struct soap*, const char*, const char*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_pututf8(struct soap*, unsigned long); +SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_getutf8(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_putbase64(struct soap*, const unsigned char*, int); +SOAP_FMAC1 unsigned char* SOAP_FMAC2 soap_getbase64(struct soap*, int*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_puthex(struct soap*, const unsigned char*, int); +SOAP_FMAC1 unsigned char* SOAP_FMAC2 soap_gethex(struct soap*, int*); + +#ifndef WITH_LEANER +SOAP_FMAC1 int SOAP_FMAC2 soap_xop_forward(struct soap*, unsigned char**, int*, char**, char**, char**); +SOAP_FMAC1 int SOAP_FMAC2 soap_dime_forward(struct soap*, unsigned char**, int*, char**, char**, char**); +#endif + +#ifndef WITH_NOIDREF +SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_lookup_id(struct soap*, void *p, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_lookup(struct soap*, const void *p, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_enter(struct soap*, const void *p, const struct soap_array *a, int n, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_array_pointer_lookup(struct soap*, const void *p, const struct soap_array *a, int n, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_embed(struct soap *soap, const void *p, const struct soap_array *a, int n, const char *tag, int type); +SOAP_FMAC1 struct soap_ilist* SOAP_FMAC2 soap_lookup(struct soap*, const char*); +SOAP_FMAC1 struct soap_ilist* SOAP_FMAC2 soap_enter(struct soap*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_resolve(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_embedded(struct soap*, const void *p, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_reference(struct soap*, const void *p, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_array_reference(struct soap*, const void *p, const struct soap_array *a, int n, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_embedded_id(struct soap*, int id, const void *p, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_is_embedded(struct soap*, struct soap_plist*); +SOAP_FMAC1 int SOAP_FMAC2 soap_is_single(struct soap*, struct soap_plist*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_embedded(struct soap*, struct soap_plist*); +#endif + +SOAP_FMAC1 int SOAP_FMAC2 soap_begin_count(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_end_count(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_begin_send(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_end_send(struct soap*); + +SOAP_FMAC1 const struct soap_code_map* SOAP_FMAC2 soap_code(const struct soap_code_map*, const char *str); +SOAP_FMAC1 long SOAP_FMAC2 soap_int_code(const struct soap_code_map*, const char *str, long other); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_str_code(const struct soap_code_map*, long code); + +SOAP_FMAC1 int SOAP_FMAC2 soap_getline(struct soap*, char*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_begin_recv(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_end_recv(struct soap*); + +SOAP_FMAC1 void* SOAP_FMAC2 soap_malloc(struct soap*, size_t); +SOAP_FMAC1 void SOAP_FMAC2 soap_dealloc(struct soap*, void*); +SOAP_FMAC1 struct soap_clist * SOAP_FMAC2 soap_link(struct soap*, void*, int, int, void (*fdelete)(struct soap_clist*)); +SOAP_FMAC1 void SOAP_FMAC2 soap_unlink(struct soap*, const void*); +SOAP_FMAC1 void SOAP_FMAC2 soap_free(struct soap*); + +SOAP_FMAC1 void* SOAP_FMAC2 soap_track_malloc(struct soap*, const char*, int, size_t); +SOAP_FMAC1 void SOAP_FMAC2 soap_track_free(struct soap*, const char*, int, void*); + +#ifndef WITH_NOIDREF +SOAP_FMAC1 int SOAP_FMAC2 soap_lookup_type(struct soap*, const char *id); +SOAP_FMAC1 void* SOAP_FMAC2 soap_id_lookup(struct soap*, const char *id, void **p, int t, size_t n, unsigned int k); +SOAP_FMAC1 void* SOAP_FMAC2 soap_id_forward(struct soap*, const char *id, void *p, int st, int tt, size_t n, unsigned int k, void(*fcopy)(struct soap*, int, int, void*, const void*, size_t)); +#endif +SOAP_FMAC1 void* SOAP_FMAC2 soap_id_enter(struct soap*, const char *id, void *p, int t, size_t n, unsigned int k, const char *type, const char *arrayType, void *(*finstantiate)(struct soap*, int, const char*, const char*, size_t*)); +SOAP_FMAC1 void SOAP_FMAC2 soap_fcopy(struct soap *soap, int st, int tt, void *p, const void *q, size_t n); + +SOAP_FMAC1 int SOAP_FMAC2 soap_size(const int *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_getoffsets(const char *, const int *, int *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_getsize(const char *, const char *, int *); +SOAP_FMAC1 int SOAP_FMAC2 soap_getsizes(const char *, int *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_getposition(const char *, int *); + +SOAP_FMAC1 char* SOAP_FMAC2 soap_putsize(struct soap*, const char *, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_putsizesoffsets(struct soap*, const char *, const int *, const int *, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_putsizes(struct soap*, const char *, const int *, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_putoffset(struct soap*, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_putoffsets(struct soap*, const int *, int); + +SOAP_FMAC1 int SOAP_FMAC2 soap_closesock(struct soap*); + +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_new(void); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_new1(soap_mode); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_new2(soap_mode, soap_mode); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_copy(struct soap*); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_copy_context(struct soap*,struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_init(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_init1(struct soap*, soap_mode); +SOAP_FMAC1 void SOAP_FMAC2 soap_init2(struct soap*, soap_mode, soap_mode); +SOAP_FMAC1 void SOAP_FMAC2 soap_done(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_cleanup(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_begin(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_end(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_delete(struct soap*, void*); + +#ifdef SOAP_DEBUG +SOAP_FMAC1 void SOAP_FMAC2 soap_set_recv_logfile(struct soap*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_sent_logfile(struct soap*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_test_logfile(struct soap*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_close_logfiles(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_open_logfile(struct soap*, int); +#endif + +SOAP_FMAC1 const char* SOAP_FMAC2 soap_token(struct soap*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_value(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_match_tag(struct soap*, const char*, const char *); +SOAP_FMAC1 int SOAP_FMAC2 soap_match_array(struct soap*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_element(struct soap*, const char*, int, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_begin_out(struct soap*, const char *tag, int id, const char *type); +SOAP_FMAC1 int SOAP_FMAC2 soap_array_begin_out(struct soap*, const char *tag, int id, const char *type, const char *offset); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_ref(struct soap*, const char *tag, int id, int href); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_href(struct soap*, const char *tag, int id, const char *ref, const char *val); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_null(struct soap*, const char *tag, int id, const char *type); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_id(struct soap*, const char *tag, int id, const void *p, const struct soap_array *a, int d, const char *type, int n); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_result(struct soap*, const char *tag); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_end_out(struct soap*, const char *tag); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_start_end_out(struct soap*, const char *tag); + +SOAP_FMAC1 int SOAP_FMAC2 soap_attribute(struct soap*, const char*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_element_begin_in(struct soap*, const char *tag, int nillable); + +SOAP_FMAC1 int SOAP_FMAC2 soap_element_end_in(struct soap*, const char *tag); + +SOAP_FMAC1 int SOAP_FMAC2 soap_peek_element(struct soap*); + +SOAP_FMAC1 void SOAP_FMAC2 soap_retry(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_revert(struct soap*); + +SOAP_FMAC1 char* SOAP_FMAC2 soap_strdup(struct soap*, const char*); +SOAP_FMAC1 const char * SOAP_FMAC2 soap_strsearch(const char *big, const char *little); + +SOAP_FMAC1 int SOAP_FMAC2 soap_string_out(struct soap*, const char *s, int flag); +SOAP_FMAC1 char* SOAP_FMAC2 soap_string_in(struct soap*, int, long, long); + +#ifndef WITH_LEANER +SOAP_FMAC1 int SOAP_FMAC2 soap_wstring_out(struct soap*, const wchar_t *s, int flag); +SOAP_FMAC1 wchar_t* SOAP_FMAC2 soap_wstring_in(struct soap*, int, long, long); +#endif + +SOAP_FMAC1 int SOAP_FMAC2 soap_match_namespace(struct soap*, const char *, const char*, int n1, int n2); + +SOAP_FMAC1 int SOAP_FMAC2 soap_set_namespaces(struct soap*, struct Namespace*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_local_namespaces(struct soap*); + +SOAP_FMAC1 void SOAP_FMAC2 soap_pop_namespace(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_push_namespace(struct soap*, const char *,const char *); + +SOAP_FMAC1 int SOAP_FMAC2 soap_store_lab(struct soap*, const char*, size_t); +SOAP_FMAC1 int SOAP_FMAC2 soap_append_lab(struct soap*, const char*, size_t); + +SOAP_FMAC1 int SOAP_FMAC2 soap_new_block(struct soap*); +SOAP_FMAC1 void* SOAP_FMAC2 soap_push_block(struct soap*, size_t); +SOAP_FMAC1 void SOAP_FMAC2 soap_pop_block(struct soap*); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_size_block(struct soap*, size_t); +SOAP_FMAC1 char* SOAP_FMAC2 soap_first_block(struct soap*); +SOAP_FMAC1 char* SOAP_FMAC2 soap_next_block(struct soap*); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_block_size(struct soap*); +SOAP_FMAC1 char* SOAP_FMAC2 soap_save_block(struct soap*, char*, int); +SOAP_FMAC1 void SOAP_FMAC2 soap_end_block(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_begin_out(struct soap*); +SOAP_FMAC1 int soap_envelope_end_out(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_begin_in(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_end_in(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_body_begin_out(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_body_end_out(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_body_begin_in(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_body_end_in(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_recv_header(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_response(struct soap*, int); + +SOAP_FMAC1 int SOAP_FMAC2 soap_send_empty_response(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_recv_empty_response(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_send_fault(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_recv_fault(struct soap*); + +#ifndef WITH_NOSTDLIB +SOAP_FMAC1 void SOAP_FMAC2 soap_print_fault(struct soap*, FILE*); +SOAP_FMAC1 void SOAP_FMAC2 soap_print_fault_location(struct soap*, FILE*); +#endif + +SOAP_FMAC1 int SOAP_FMAC2 soap_s2byte(struct soap*, const char*, char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2short(struct soap*, const char*, short*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2int(struct soap*, const char*, int*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2long(struct soap*, const char*, long*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2LONG64(struct soap*, const char*, LONG64*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2float(struct soap*, const char*, float*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2double(struct soap*, const char*, double*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedByte(struct soap*, const char*, unsigned char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedShort(struct soap*, const char*, unsigned short*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedInt(struct soap*, const char*, unsigned int*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedLong(struct soap*, const char*, unsigned long*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2ULONG64(struct soap*, const char*, ULONG64*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2string(struct soap*, const char*, char**); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2QName(struct soap*, const char*, char**); + +#ifndef WITH_LEAN +SOAP_FMAC1 int SOAP_FMAC2 soap_s2dateTime(struct soap*, const char*, time_t*); +SOAP_FMAC1 char* SOAP_FMAC2 soap_s2base64(struct soap*, const unsigned char*, char*, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_s2hex(struct soap*, const unsigned char*, char*, int); +#endif + +SOAP_FMAC1 const char* SOAP_FMAC2 soap_byte2s(struct soap*, char); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_short2s(struct soap*, short); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_int2s(struct soap*, int); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_long2s(struct soap*, long); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_LONG642s(struct soap*, LONG64); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_float2s(struct soap*, float); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_double2s(struct soap*, double); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedByte2s(struct soap*, unsigned char); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedShort2s(struct soap*, unsigned short); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedInt2s(struct soap*, unsigned int); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedLong2s(struct soap*, unsigned long); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_ULONG642s(struct soap*, ULONG64); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_QName2s(struct soap*, const char*); + +#ifndef WITH_LEAN +SOAP_FMAC1 const char* SOAP_FMAC2 soap_dateTime2s(struct soap*, time_t); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_base642s(struct soap*, const char*, char*, size_t, int*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_hex2s(struct soap*, const char*, char*, size_t, int*); +#endif + + +SOAP_FMAC1 int* SOAP_FMAC2 soap_inint(struct soap*, const char *tag, int *p, const char *, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_inbyte(struct soap*, const char *tag, char *p, const char *, int); +SOAP_FMAC1 long* SOAP_FMAC2 soap_inlong(struct soap*, const char *tag, long *p, const char *, int); +SOAP_FMAC1 LONG64* SOAP_FMAC2 soap_inLONG64(struct soap*, const char *tag, LONG64 *p, const char *, int); +SOAP_FMAC1 short* SOAP_FMAC2 soap_inshort(struct soap*, const char *tag, short *p, const char *, int); +SOAP_FMAC1 float* SOAP_FMAC2 soap_infloat(struct soap*, const char *tag, float *p, const char *, int); +SOAP_FMAC1 double* SOAP_FMAC2 soap_indouble(struct soap*, const char *tag, double *p, const char *, int); +SOAP_FMAC1 unsigned char* SOAP_FMAC2 soap_inunsignedByte(struct soap*, const char *tag, unsigned char *p, const char *, int); +SOAP_FMAC1 unsigned short* SOAP_FMAC2 soap_inunsignedShort(struct soap*, const char *tag, unsigned short *p, const char *, int); +SOAP_FMAC1 unsigned int* SOAP_FMAC2 soap_inunsignedInt(struct soap*, const char *tag, unsigned int *p, const char *, int); +SOAP_FMAC1 unsigned long* SOAP_FMAC2 soap_inunsignedLong(struct soap*, const char *tag, unsigned long *p, const char *, int); +SOAP_FMAC1 ULONG64* SOAP_FMAC2 soap_inULONG64(struct soap*, const char *tag, ULONG64 *p, const char *, int); +SOAP_FMAC1 char** SOAP_FMAC2 soap_instring(struct soap*, const char *tag, char **p, const char *, int, int, long, long); +SOAP_FMAC1 char** SOAP_FMAC2 soap_inliteral(struct soap*, const char *tag, char **p); + +#ifndef WITH_LEAN +SOAP_FMAC1 time_t* SOAP_FMAC2 soap_indateTime(struct soap*, const char *tag, time_t *p, const char *, int); +#endif + +#ifndef WITH_LEANER +SOAP_FMAC1 wchar_t** SOAP_FMAC2 soap_inwstring(struct soap*, const char *tag, wchar_t **p, const char *, int, long, long); +SOAP_FMAC1 wchar_t** SOAP_FMAC2 soap_inwliteral(struct soap*, const char *tag, wchar_t **p); +#endif + +SOAP_FMAC1 int SOAP_FMAC2 soap_outbyte(struct soap*, const char *tag, int id, const char *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outshort(struct soap*, const char *tag, int id, const short *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outint(struct soap*, const char *tag, int id, const int *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outlong(struct soap*, const char *tag, int id, const long *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outLONG64(struct soap*, const char *tag, int id, const LONG64 *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outfloat(struct soap*, const char *tag, int id, const float *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outdouble(struct soap*, const char *tag, int id, const double *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedByte(struct soap*, const char *tag, int id, const unsigned char *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedShort(struct soap*, const char *tag, int id, const unsigned short *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedInt(struct soap*, const char *tag, int id, const unsigned int *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedLong(struct soap*, const char *tag, int id, const unsigned long *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outULONG64(struct soap*, const char *tag, int id, const ULONG64 *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outstring(struct soap*, const char *tag, int id, char *const*p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outliteral(struct soap*, const char *tag, char *const*p); + +#ifndef WITH_LEAN +SOAP_FMAC1 int SOAP_FMAC2 soap_outdateTime(struct soap*, const char *tag, int id, const time_t *p, const char *, int); +#endif + +#ifndef WITH_LEANER +SOAP_FMAC1 int SOAP_FMAC2 soap_outwstring(struct soap*, const char *tag, int id, wchar_t *const*p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outwliteral(struct soap*, const char *tag, wchar_t *const*p); +#endif + +#ifndef WITH_LEANER +SOAP_FMAC1 int SOAP_FMAC2 soap_attachment(struct soap *, const char*, int, const void*, const struct soap_array*, const char*, const char*, const char*, int, const char*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_move(struct soap*, long); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_tell(struct soap*); +SOAP_FMAC1 char* SOAP_FMAC2 soap_dime_option(struct soap*, unsigned short, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getdimehdr(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getdime(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putdimehdr(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putdime(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getmimehdr(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getmime(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putmimehdr(struct soap*, struct soap_multipart*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putmime(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_dime(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_mime(struct soap*, const char *boundary, const char *start); +SOAP_FMAC1 void SOAP_FMAC2 soap_clr_dime(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_clr_mime(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_dime_attachment(struct soap*, char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_mime_attachment(struct soap*, char *ptr, size_t size, enum soap_mime_encoding encoding, const char *type, const char *id, const char *location, const char *description); +SOAP_FMAC1 struct soap_multipart* SOAP_FMAC2 soap_next_multipart(struct soap_multipart*); +#endif + +SOAP_FMAC1 int SOAP_FMAC2 soap_register_plugin_arg(struct soap*, int (*fcreate)(struct soap*, struct soap_plugin*, void*), void*); +SOAP_FMAC1 void* SOAP_FMAC2 soap_lookup_plugin(struct soap*, const char*); + +SOAP_FMAC1 const char* SOAP_FMAC2 soap_attr_value(struct soap *soap, const char *name, int flag); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_attr(struct soap *soap, const char *name, const char *value); +SOAP_FMAC1 void SOAP_FMAC2 soap_clr_attr(struct soap *soap); + +#ifdef WITH_COOKIES +SOAP_FMAC1 size_t SOAP_FMAC2 soap_encode_cookie(const char*, char*, size_t); +SOAP_FMAC1 extern struct soap_cookie* SOAP_FMAC2 soap_set_cookie(struct soap*, const char*, const char*, const char*, const char*); +SOAP_FMAC1 extern struct soap_cookie* SOAP_FMAC2 soap_cookie(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern char* SOAP_FMAC2 soap_cookie_value(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern char* SOAP_FMAC2 soap_env_cookie_value(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern long SOAP_FMAC2 soap_cookie_expire(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern int SOAP_FMAC2 soap_set_cookie_expire(struct soap*, const char*, long, const char*, const char*); +SOAP_FMAC1 extern int SOAP_FMAC2 soap_set_cookie_session(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern int SOAP_FMAC2 soap_clr_cookie_session(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern void SOAP_FMAC2 soap_clr_cookie(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern int SOAP_FMAC2 soap_getenv_cookies(struct soap*); +SOAP_FMAC1 extern struct soap_cookie* SOAP_FMAC2 soap_copy_cookies(struct soap*); +SOAP_FMAC1 extern void SOAP_FMAC2 soap_free_cookies(struct soap*); +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif + diff --git a/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.6d.c b/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.6d.c new file mode 100644 index 0000000..461bea7 --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.6d.c @@ -0,0 +1,13362 @@ +/* + +stdsoap2.c[pp] 2.7.6d + +gSOAP runtime + +gSOAP XML Web services tools +Copyright (C) 2000-2005, Robert van Engelen, Genivia Inc., All Rights Reserved. +This part of the software is released under one of the following licenses: +GPL, the gSOAP public license, or Genivia's license for commercial use. +-------------------------------------------------------------------------------- +Contributors: + +Wind River Systems Inc., for the following additions under gSOAP public license: + - vxWorks compatible (#define VXWORKS) +-------------------------------------------------------------------------------- +gSOAP public license. + +The contents of this file are subject to the gSOAP Public License Version 1.3 +(the "License"); you may not use this file except in compliance with the +License. You may obtain a copy of the License at +http://www.cs.fsu.edu/~engelen/soaplicense.html +Software distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +for the specific language governing rights and limitations under the License. + +The Initial Developer of the Original Code is Robert A. van Engelen. +Copyright (C) 2000-2005, Robert van Engelen, Genivia Inc., All Rights Reserved. +-------------------------------------------------------------------------------- +GPL license. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA + +Author contact information: +engelen@genivia.com / engelen@acm.org +-------------------------------------------------------------------------------- +A commercial use license is available from Genivia, Inc., contact@genivia.com +-------------------------------------------------------------------------------- + +Installation note: + +Win32 build needs winsock.dll (Visual C++ "wsock32.lib") +To do this in Visual C++ 6.0, go to "Project", "settings", select the "Link" +tab (the project file needs to be selected in the file view) and add +"wsock32.lib" to the "Object/library modules" entry + +On Mac OS X with gcc (GCC) 3.1 20020420 (prerelease) you MUST compile with +-fstack_check when using -O2 because gcc 3.1 has a bug that smashes the stack +when locally allocated data exceeds 64K. + +*/ + +#ifdef AS400 +# pragma convert(819) /* EBCDIC to ASCII */ +#endif + +#include "stdsoap2.h" + +#ifdef __cplusplus +SOAP_SOURCE_STAMP("@(#) stdsoap2.cpp ver 2.7.6d 2005-12-29 12:00:00 GMT") +extern "C" { +#else +SOAP_SOURCE_STAMP("@(#) stdsoap2.c ver 2.7.6d 2005-12-29 12:00:00 GMT") +#endif + +/* 8bit character representing unknown/nonrepresentable character data (e.g. not supported by current locale with multibyte support enabled) */ +#ifndef SOAP_UNKNOWN_CHAR +#define SOAP_UNKNOWN_CHAR (127) +#endif + +/* EOF=-1 */ +#define SOAP_LT (soap_wchar)(-2) /* XML character '<' */ +#define SOAP_TT (soap_wchar)(-3) /* XML character '' */ +#define SOAP_QT (soap_wchar)(-5) /* XML character '"' */ +#define SOAP_AP (soap_wchar)(-6) /* XML character ''' */ + +#define soap_blank(c) ((c) >= 0 && (c) <= 32) +#define soap_notblank(c) ((c) > 32) +#define soap_hash_ptr(p) (((unsigned long)(p) >> 3) & (SOAP_PTRHASH - 1)) + +#ifdef SOAP_DEBUG +static void soap_init_logs(struct soap*); +static void soap_close_logfile(struct soap*, int); +static void soap_set_logfile(struct soap*, int, const char*); +static void soap_free_mht(struct soap*); +static void soap_track_unlink(struct soap*, const void*); +#endif + +#ifndef PALM_2 +static int soap_set_error(struct soap*, const char*, const char*, const char*, const char*, int); +static int soap_copy_fault(struct soap*, const char*, const char*, const char*, const char*); +static int soap_getattrval(struct soap*, char*, size_t, soap_wchar); +#endif + +#ifndef PALM_1 +static soap_wchar soap_char(struct soap*); +static soap_wchar soap_get_pi(struct soap*); +static int soap_isxdigit(int); +static void *fplugin(struct soap*, const char*); +#ifndef WITH_NOIDREF +static void soap_update_ptrs(struct soap*, char*, char*, long); +static int soap_has_copies(struct soap*, const char*, const char*); +static void soap_init_iht(struct soap*); +static void soap_free_iht(struct soap*); +static void soap_init_pht(struct soap*); +static void soap_free_pht(struct soap*); +#endif +#endif + +#ifndef WITH_LEAN +static const char *soap_set_validation_fault(struct soap*, const char*, const char*); +static int soap_isnumeric(struct soap*, const char*); +static time_t soap_timegm(struct tm*); +static struct soap_nlist *soap_lookup_ns(struct soap *soap, const char *tag, size_t n); +static struct soap_nlist *soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized); +static void soap_pop_ns(struct soap *soap); +static void soap_utilize_ns(struct soap *soap, const char *tag, size_t n); +#endif + +#ifndef WITH_LEANER +#ifndef PALM_1 +static struct soap_multipart *soap_new_multipart(struct soap*, struct soap_multipart**, struct soap_multipart**, char*, size_t); +static int soap_putdimefield(struct soap*, const char*, size_t); +static char *soap_getdimefield(struct soap*, size_t); +static void soap_select_mime_boundary(struct soap*); +static int soap_valid_mime_boundary(struct soap*); +static int soap_match_cid(struct soap*, const char*, const char*); +static void soap_resolve_attachment(struct soap*, struct soap_multipart*); +#endif +#endif + +#ifdef WITH_GZIP +static int soap_getgziphdr(struct soap*); +#endif + +#ifdef WITH_OPENSSL +static void ssl_init(); +static int ssl_auth_init(struct soap*); +static int ssl_verify_callback(int, X509_STORE_CTX*); +static int ssl_password(char*, int, int, void *); +static const char *ssl_error(struct soap*, int); +/* This callback is included for future references. It should not be deleted +static DH *ssl_tmp_dh(SSL*, int, int); +*/ +#endif + +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +#ifndef PALM_1 +static const char *soap_decode(char*, size_t, const char*, const char*); +#endif +#endif + +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static soap_wchar soap_getchunkchar(struct soap*); +static const char *http_error(struct soap*, int); +static int http_post(struct soap*, const char*, const char*, int, const char*, const char*, size_t); +static int http_get(struct soap*); +static int http_send_header(struct soap*, const char*); +static int http_post_header(struct soap*, const char*, const char*); +static int http_response(struct soap*, int, size_t); +static int http_parse(struct soap*); +static int http_parse_header(struct soap*, const char*, const char*); +#endif +#endif + +#ifndef WITH_NOIO +#ifndef PALM_1 +static int fsend(struct soap*, const char*, size_t); +static size_t frecv(struct soap*, char*, size_t); +static int tcp_init(struct soap*); +static const char *tcp_error(struct soap*); +#ifndef WITH_IPV6 +static int tcp_gethost(struct soap*, const char *addr, struct in_addr *inaddr); +#endif +static int tcp_connect(struct soap*, const char *endpoint, const char *host, int port); +static int tcp_accept(struct soap*, int, struct sockaddr*, int*); +static int tcp_disconnect(struct soap*); +static int tcp_closesocket(struct soap*, SOAP_SOCKET); +static int tcp_shutdownsocket(struct soap*, SOAP_SOCKET, int); +static const char *soap_strerror(struct soap*); +#endif +#endif + +#if defined(PALM) && !defined(PALM_2) +unsigned short errno; +#endif + +#ifndef PALM_1 +static const char soap_env1[42] = "http://schemas.xmlsoap.org/soap/envelope/"; +static const char soap_enc1[42] = "http://schemas.xmlsoap.org/soap/encoding/"; +static const char soap_env2[40] = "http://www.w3.org/2003/05/soap-envelope"; +static const char soap_enc2[40] = "http://www.w3.org/2003/05/soap-encoding"; +static const char soap_rpc[35] = "http://www.w3.org/2003/05/soap-rpc"; +#endif + +#ifndef PALM_1 +const struct soap_double_nan soap_double_nan = {0xFFFFFFFF, 0xFFFFFFFF}; +static const char soap_base64o[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char soap_base64i[81] = "\76XXX\77\64\65\66\67\70\71\72\73\74\75XXXXXXX\00\01\02\03\04\05\06\07\10\11\12\13\14\15\16\17\20\21\22\23\24\25\26\27\30\31XXXXXX\32\33\34\35\36\37\40\41\42\43\44\45\46\47\50\51\52\53\54\55\56\57\60\61\62\63"; +#endif + +#ifndef WITH_LEAN +static const char soap_indent[11] = "\n\t\t\t\t\t\t\t\t\t"; +/* Alternative indentation form for SOAP_XML_INDENT: +static const char soap_indent[21] = "\n "; +*/ +#endif + +static const char soap_padding[4] = "\0\0\0"; +#define SOAP_STR_PADDING (soap_padding) +#define SOAP_STR_EOS (soap_padding) +#define SOAP_NON_NULL (soap_padding) + +#ifndef WITH_LEAN +static const struct soap_code_map html_entity_codes[] = /* entities for XHTML parsing */ +{ { 160, "nbsp" }, + { 161, "iexcl" }, + { 162, "cent" }, + { 163, "pound" }, + { 164, "curren" }, + { 165, "yen" }, + { 166, "brvbar" }, + { 167, "sect" }, + { 168, "uml" }, + { 169, "copy" }, + { 170, "ordf" }, + { 171, "laquo" }, + { 172, "not" }, + { 173, "shy" }, + { 174, "reg" }, + { 175, "macr" }, + { 176, "deg" }, + { 177, "plusmn" }, + { 178, "sup2" }, + { 179, "sup3" }, + { 180, "acute" }, + { 181, "micro" }, + { 182, "para" }, + { 183, "middot" }, + { 184, "cedil" }, + { 185, "sup1" }, + { 186, "ordm" }, + { 187, "raquo" }, + { 188, "frac14" }, + { 189, "frac12" }, + { 190, "frac34" }, + { 191, "iquest" }, + { 192, "Agrave" }, + { 193, "Aacute" }, + { 194, "Acirc" }, + { 195, "Atilde" }, + { 196, "Auml" }, + { 197, "Aring" }, + { 198, "AElig" }, + { 199, "Ccedil" }, + { 200, "Egrave" }, + { 201, "Eacute" }, + { 202, "Ecirc" }, + { 203, "Euml" }, + { 204, "Igrave" }, + { 205, "Iacute" }, + { 206, "Icirc" }, + { 207, "Iuml" }, + { 208, "ETH" }, + { 209, "Ntilde" }, + { 210, "Ograve" }, + { 211, "Oacute" }, + { 212, "Ocirc" }, + { 213, "Otilde" }, + { 214, "Ouml" }, + { 215, "times" }, + { 216, "Oslash" }, + { 217, "Ugrave" }, + { 218, "Uacute" }, + { 219, "Ucirc" }, + { 220, "Uuml" }, + { 221, "Yacute" }, + { 222, "THORN" }, + { 223, "szlig" }, + { 224, "agrave" }, + { 225, "aacute" }, + { 226, "acirc" }, + { 227, "atilde" }, + { 228, "auml" }, + { 229, "aring" }, + { 230, "aelig" }, + { 231, "ccedil" }, + { 232, "egrave" }, + { 233, "eacute" }, + { 234, "ecirc" }, + { 235, "euml" }, + { 236, "igrave" }, + { 237, "iacute" }, + { 238, "icirc" }, + { 239, "iuml" }, + { 240, "eth" }, + { 241, "ntilde" }, + { 242, "ograve" }, + { 243, "oacute" }, + { 244, "ocirc" }, + { 245, "otilde" }, + { 246, "ouml" }, + { 247, "divide" }, + { 248, "oslash" }, + { 249, "ugrave" }, + { 250, "uacute" }, + { 251, "ucirc" }, + { 252, "uuml" }, + { 253, "yacute" }, + { 254, "thorn" }, + { 255, "yuml" }, + { 0, NULL } +}; +#endif + +#ifndef WITH_NOIO +#ifndef WITH_LEAN +static const struct soap_code_map h_error_codes[] = +{ +#ifdef HOST_NOT_FOUND + { HOST_NOT_FOUND, "Host not found" }, +#endif +#ifdef TRY_AGAIN + { TRY_AGAIN, "Try Again" }, +#endif +#ifdef NO_RECOVERY + { NO_RECOVERY, "No Recovery" }, +#endif +#ifdef NO_DATA + { NO_DATA, "No Data" }, +#endif +#ifdef NO_ADDRESS + { NO_ADDRESS, "No Address" }, +#endif + { 0, NULL } +}; +#endif +#endif + +#ifndef WITH_NOHTTP +#ifndef WITH_LEAN +static const struct soap_code_map h_http_error_codes[] = +{ { 201, "Created" }, + { 202, "Accepted" }, + { 203, "Non-Authoritative Information" }, + { 204, "No Content" }, + { 205, "Reset Content" }, + { 206, "Partial Content" }, + { 300, "Multiple Choices" }, + { 301, "Moved Permanently" }, + { 302, "Found" }, + { 303, "See Other" }, + { 304, "Not Modified" }, + { 305, "Use Proxy" }, + { 307, "Temporary Redirect" }, + { 400, "Bad Request" }, + { 401, "Unauthorized" }, + { 402, "Payment Required" }, + { 403, "Forbidden" }, + { 404, "Not Found" }, + { 405, "Method Not Allowed" }, + { 406, "Not Acceptable" }, + { 407, "Proxy Authentication Required" }, + { 408, "Request Time-out" }, + { 409, "Conflict" }, + { 410, "Gone" }, + { 411, "Length Required" }, + { 412, "Precondition Failed" }, + { 413, "Request Entity Too Large" }, + { 414, "Request-URI Too Large" }, + { 415, "Unsupported Media Type" }, + { 416, "Requested range not satisfiable" }, + { 417, "Expectation Failed" }, + { 500, "Internal Server Error" }, + { 501, "Not Implemented" }, + { 502, "Bad Gateway" }, + { 503, "Service Unavailable" }, + { 504, "Gateway Time-out" }, + { 505, "HTTP Version not supported" }, + { 0, NULL } +}; +#endif +#endif + +#ifdef WITH_OPENSSL +static const struct soap_code_map h_ssl_error_codes[] = +{ +#define _SSL_ERROR(e) { e, #e } + _SSL_ERROR(SSL_ERROR_SSL), + _SSL_ERROR(SSL_ERROR_ZERO_RETURN), + _SSL_ERROR(SSL_ERROR_WANT_READ), + _SSL_ERROR(SSL_ERROR_WANT_WRITE), + _SSL_ERROR(SSL_ERROR_WANT_CONNECT), + _SSL_ERROR(SSL_ERROR_WANT_X509_LOOKUP), + _SSL_ERROR(SSL_ERROR_SYSCALL), + { 0, NULL } +}; +#endif + +#ifndef WITH_LEANER +static const struct soap_code_map mime_codes[] = +{ { SOAP_MIME_7BIT, "7bit" }, + { SOAP_MIME_8BIT, "8bit" }, + { SOAP_MIME_BINARY, "binary" }, + { SOAP_MIME_QUOTED_PRINTABLE, "quoted-printable" }, + { SOAP_MIME_BASE64, "base64" }, + { SOAP_MIME_IETF_TOKEN, "ietf-token" }, + { SOAP_MIME_X_TOKEN, "x-token" }, + { 0, NULL } +}; +#endif + +#ifdef WIN32 +static int tcp_done = 0; +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +fsend(struct soap *soap, const char *s, size_t n) +{ register int nwritten; +#if defined(__cplusplus) && !defined(WITH_LEAN) + if (soap->os) + { soap->os->write(s, n); + if (soap->os->good()) + return SOAP_OK; + return SOAP_EOF; + } +#endif + while (n) + { if (soap_valid_socket(soap->socket)) + { +#ifndef WITH_LEAN + if (soap->send_timeout) + { struct timeval timeout; + fd_set fd; + if (soap->send_timeout > 0) + { timeout.tv_sec = soap->send_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->send_timeout/1000000; + timeout.tv_usec = -soap->send_timeout%1000000; + } + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->socket, &fd); + for (;;) + { register int r = select((SOAP_SOCKET)(soap->socket + 1), NULL, &fd, &fd, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + return SOAP_EOF; + } + if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EAGAIN) + { soap->errnum = soap_socket_errno; + return SOAP_EOF; + } + } + } +#endif +#ifdef WITH_OPENSSL + if (soap->ssl) + nwritten = SSL_write(soap->ssl, s, n); + else if (soap->bio) + nwritten = BIO_write(soap->bio, s, n); + else +#endif +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + { if (soap->peerlen) + nwritten = sendto((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags, (struct sockaddr*)&soap->peer, soap->peerlen); + else + nwritten = send((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags); + /* retry and back-off algorithm */ + /* TODO: this is not very clear from specs so verify and limit conditions under which we should loop (e.g. ENOBUFS) */ + if (nwritten < 0) + { struct timeval timeout; + fd_set fd; + int udp_repeat; + int udp_delay; + if ((soap->connect_flags & SO_BROADCAST)) + udp_repeat = 3; /* SOAP-over-UDP MULTICAST_UDP_REPEAT - 1 */ + else + udp_repeat = 1; /* SOAP-over-UDP UNICAST_UDP_REPEAT - 1 */ + udp_delay = (soap_random % 201) + 50; /* UDP_MIN_DELAY .. UDP_MAX_DELAY */ + do + { timeout.tv_sec = 0; + timeout.tv_usec = 1000 * udp_delay; /* ms */ + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->socket, &fd); + select((SOAP_SOCKET)(soap->socket + 1), NULL, NULL, &fd, &timeout); + if (soap->peerlen) + nwritten = sendto((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags, (struct sockaddr*)&soap->peer, soap->peerlen); + else + nwritten = send((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags); + udp_delay <<= 1; + if (udp_delay > 500) /* UDP_UPPER_DELAY */ + udp_delay = 500; + } + while (nwritten < 0 && --udp_repeat > 0); + } + } + else +#endif +#if !defined(PALM) && !defined(AS400) + nwritten = send((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags); +#else + nwritten = send((SOAP_SOCKET)soap->socket, (void*)s, n, soap->socket_flags); +#endif + if (nwritten <= 0) + { +#ifdef WITH_OPENSSL + int err; + if (soap->ssl && (err = SSL_get_error(soap->ssl, nwritten)) != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) + return SOAP_EOF; +#endif + if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EWOULDBLOCK && soap_socket_errno != SOAP_EAGAIN) + { soap->errnum = soap_socket_errno; + return SOAP_EOF; + } + nwritten = 0; /* and call write() again */ + } + } + else + { +#ifdef WITH_FASTCGI + nwritten = fwrite((void*)s, 1, n, stdout); + fflush(stdout); +#else +#ifdef UNDER_CE + nwritten = fwrite(s, 1, n, soap->sendfd); +#else +#ifdef VXWORKS +#ifdef WMW_RPM_IO + if (soap->rpmreqid) + nwritten = (httpBlockPut(soap->rpmreqid, s, n) == 0) ? n : -1; + else +#endif + nwritten = fwrite(s, sizeof(char), n, fdopen(soap->sendfd, "w")); +#else + nwritten = write((SOAP_SOCKET)soap->sendfd, s, n); +#endif +#endif +#endif + if (nwritten <= 0) + { if (soap_errno != SOAP_EINTR && soap_errno != SOAP_EWOULDBLOCK && soap_errno != SOAP_EAGAIN) + { soap->errnum = soap_errno; + return SOAP_EOF; + } + nwritten = 0; /* and call write() again */ + } + } + n -= nwritten; + s += nwritten; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send_raw(struct soap *soap, const char *s, size_t n) +{ if (!n) + return SOAP_OK; + if (soap->mode & SOAP_IO_LENGTH) + { soap->count += n; +#ifndef WITH_LEANER + if (soap->fpreparesend && (soap->mode & SOAP_IO) != SOAP_IO_STORE) + return soap->error = soap->fpreparesend(soap, s, n); +#endif + return SOAP_OK; + } + if (soap->mode & SOAP_IO) + { register size_t i = SOAP_BUFLEN - soap->bufidx; + while (n >= i) + { memcpy(soap->buf + soap->bufidx, s, i); + soap->bufidx = SOAP_BUFLEN; + if (soap_flush(soap)) + return soap->error; + s += i; + n -= i; + i = SOAP_BUFLEN; + } + memcpy(soap->buf + soap->bufidx, s, n); + soap->bufidx += n; + return SOAP_OK; + } + return soap_flush_raw(soap, s, n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_flush(struct soap *soap) +{ register int n = soap->bufidx; + if (n) + { soap->bufidx = 0; +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { soap->d_stream.next_in = (Byte*)soap->buf; + soap->d_stream.avail_in = (unsigned int)n; +#ifdef WITH_GZIP + soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)n); +#endif + do + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating %u bytes\n", soap->d_stream.avail_in)); + if (deflate(&soap->d_stream, Z_NO_FLUSH) != Z_OK) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to deflate: %s\n", soap->d_stream.msg?soap->d_stream.msg:"")); + return soap->error = SOAP_ZLIB_ERROR; + } + if (!soap->d_stream.avail_out) + { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN)) + return soap->error; + soap->d_stream.next_out = (Byte*)soap->z_buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + } + } while (soap->d_stream.avail_in); + } + else +#endif + return soap_flush_raw(soap, soap->buf, n); + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_flush_raw(struct soap *soap, const char *s, size_t n) +{ if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) + { register char *t; + if (!(t = (char*)soap_push_block(soap, n))) + return soap->error = SOAP_EOM; + memcpy(t, s, n); +#ifndef WITH_LEANER + if (soap->fpreparesend) + return soap->error = soap->fpreparesend(soap, s, n); +#endif + return SOAP_OK; + } +#ifndef WITH_LEANER + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) + { char t[16]; + sprintf(t, "\r\n%lX\r\n" + (soap->chunksize ? 0 : 2), (unsigned long)n); + DBGMSG(SENT, t, strlen(t)); + if ((soap->error = soap->fsend(soap, t, strlen(t)))) + return soap->error; + soap->chunksize += n; + } + DBGMSG(SENT, s, n); +#endif + return soap->error = soap->fsend(soap, s, n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send(struct soap *soap, const char *s) +{ if (s) + return soap_send_raw(soap, s, strlen(s)); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send2(struct soap *soap, const char *s1, const char *s2) +{ if (soap_send(soap, s1)) + return soap->error; + return soap_send(soap, s2); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send3(struct soap *soap, const char *s1, const char *s2, const char *s3) +{ if (soap_send(soap, s1) + || soap_send(soap, s2)) + return soap->error; + return soap_send(soap, s3); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static size_t +frecv(struct soap *soap, char *s, size_t n) +{ register int r; + soap->errnum = 0; +#if defined(__cplusplus) && !defined(WITH_LEAN) + if (soap->is) + { if (soap->is->good()) + return soap->is->read(s, n).gcount(); + return 0; + } +#endif + if (soap_valid_socket(soap->socket)) + { for (;;) + { +#ifndef WITH_LEAN + if (soap->recv_timeout) + { struct timeval timeout; + fd_set fd; + if (soap->recv_timeout > 0) + { timeout.tv_sec = soap->recv_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->recv_timeout/1000000; + timeout.tv_usec = -soap->recv_timeout%1000000; + } + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->socket, &fd); + for (;;) + { r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + return 0; + } + if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EAGAIN) + { soap->errnum = soap_socket_errno; + return 0; + } + } + } +#endif +#ifdef WITH_OPENSSL + if (soap->ssl) + { int err; + r = SSL_read(soap->ssl, s, n); + if (r > 0) + return (size_t)r; + err = SSL_get_error(soap->ssl, r); + if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) + return 0; + } + else if (soap->bio) + { r = BIO_read(soap->bio, s, n); + if (r > 0) + return (size_t)r; + return 0; + } + else +#endif + { +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + { SOAP_SOCKLEN_T k = (SOAP_SOCKLEN_T)sizeof(soap->peer); + memset((void*)&soap->peer, 0, sizeof(soap->peer)); + r = recvfrom((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags, (struct sockaddr*)&soap->peer, &k); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */ + soap->peerlen = (size_t)k; +#ifndef WITH_IPV6 + soap->ip = ntohl(soap->peer.sin_addr.s_addr); + soap->port = (int)ntohs(soap->peer.sin_port); +#endif + } + else +#endif + r = recv((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags); + if (r >= 0) + return (size_t)r; + if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EAGAIN && soap_socket_errno != SOAP_EWOULDBLOCK) + { soap->errnum = soap_socket_errno; + return 0; + } + } +#ifndef WITH_LEAN + { struct timeval timeout; + fd_set fd; + timeout.tv_sec = 0; + timeout.tv_usec = 10000; + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->socket, &fd); +#ifdef WITH_OPENSSL + if (soap->ssl && SSL_get_error(soap->ssl, r) == SSL_ERROR_WANT_WRITE) + r = select((SOAP_SOCKET)(soap->socket + 1), NULL, &fd, &fd, &timeout); + else + r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout); +#else + r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout); +#endif + if (r < 0 && soap_socket_errno != SOAP_EINTR) + { soap->errnum = soap_socket_errno; + return 0; + } + } +#endif + } + } +#ifdef WITH_FASTCGI + return fread(s, 1, n, stdin); +#else +#ifdef UNDER_CE + return fread(s, 1, n, soap->recvfd); +#else +#ifdef WMW_RPM_IO + if (soap->rpmreqid) + r = httpBlockRead(soap->rpmreqid, s, n); + else +#endif + r = read((SOAP_SOCKET)soap->recvfd, s, n); + if (r >= 0) + return (size_t)r; + soap->errnum = soap_errno; + return 0; +#endif +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static soap_wchar +soap_getchunkchar(struct soap *soap) +{ if (soap->bufidx < soap->buflen) + return soap->buf[soap->bufidx++]; + soap->bufidx = 0; + soap->buflen = soap->chunkbuflen = soap->frecv(soap, soap->buf, SOAP_BUFLEN); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket %d\n", (unsigned int)soap->buflen, soap->socket)); + DBGMSG(RECV, soap->buf, soap->buflen); + if (soap->buflen) + return soap->buf[soap->bufidx++]; + return EOF; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +soap_isxdigit(int c) +{ return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv_raw(struct soap *soap) +{ register size_t ret; +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { if (soap->d_stream.next_out == Z_NULL) + return EOF; + if (soap->d_stream.avail_in || !soap->d_stream.avail_out) + { register int r; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflating\n")); + soap->d_stream.next_out = (Byte*)soap->buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + r = inflate(&soap->d_stream, Z_NO_FLUSH); + if (r == Z_OK || r == Z_STREAM_END) + { soap->bufidx = 0; + soap->buflen = SOAP_BUFLEN - soap->d_stream.avail_out; + if (soap->zlib_in == SOAP_ZLIB_GZIP) + soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen); + if (r == Z_STREAM_END) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out)); + soap->z_ratio_in = (float)soap->d_stream.total_in / (float)soap->d_stream.total_out; + soap->d_stream.next_out = Z_NULL; + } + if (soap->buflen) + { soap->count += soap->buflen; + return SOAP_OK; + } + } + else if (r != Z_BUF_ERROR) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate error: %s\n", soap->d_stream.msg?soap->d_stream.msg:"")); + soap->d_stream.next_out = Z_NULL; + soap->error = SOAP_ZLIB_ERROR; + return EOF; + } + } +zlib_again: + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK && !soap->chunksize) + { memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN); + soap->buflen = soap->z_buflen; + } + } +#endif +#ifndef WITH_NOHTTP + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) /* read HTTP chunked transfer */ + { +chunk_again: + if (soap->chunksize) + { soap->buflen = ret = soap->frecv(soap, soap->buf, soap->chunksize > SOAP_BUFLEN ? SOAP_BUFLEN : soap->chunksize); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk: read %u bytes\n", (unsigned int)ret)); + DBGMSG(RECV, soap->buf, ret); + soap->bufidx = 0; + soap->chunksize -= ret; + } + else + { register soap_wchar c; + char *t, tmp[8]; + t = tmp; + if (!soap->chunkbuflen) + { soap->chunkbuflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes (chunked) from socket %d\n", (unsigned int)ret, soap->socket)); + DBGMSG(RECV, soap->buf, ret); + soap->bufidx = 0; + if (!ret) + return soap->ahead = EOF; + } + else + soap->bufidx = soap->buflen; + soap->buflen = soap->chunkbuflen; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk size (idx=%u len=%u)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen)); + while (!soap_isxdigit((int)(c = soap_getchunkchar(soap)))) + if ((int)c == EOF) + return soap->ahead = EOF; + do + *t++ = (char)c; + while (soap_isxdigit((int)(c = soap_getchunkchar(soap))) && t - tmp < 7); + while ((int)c != EOF && c != '\n') + c = soap_getchunkchar(soap); + if ((int)c == EOF) + return soap->ahead = EOF; + *t = '\0'; + soap->chunksize = soap_strtoul(tmp, &t, 16); + if (!soap->chunksize) + { soap->chunkbuflen = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of chunked message\n")); + while ((int)c != EOF && c != '\n') + c = soap_getchunkchar(soap); + return soap->ahead = EOF; + } + soap->buflen = soap->bufidx + soap->chunksize; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving buf len to idx=%u len=%u (%s)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen, tmp)); + if (soap->buflen > soap->chunkbuflen) + { soap->buflen = soap->chunkbuflen; + soap->chunksize -= soap->buflen - soap->bufidx; + soap->chunkbuflen = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Passed end of buffer for chunked HTTP (%u bytes left)\n", (unsigned int)(soap->buflen - soap->bufidx))); + } + else if (soap->chunkbuflen) + soap->chunksize = 0; + ret = soap->buflen - soap->bufidx; + if (!ret) + goto chunk_again; + } + } + else +#endif + { soap->bufidx = 0; + soap->buflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket %d\n", (unsigned int)ret, soap->socket)); + DBGMSG(RECV, soap->buf, ret); + } +#ifndef WITH_LEANER + if (soap->fpreparerecv && (soap->error = soap->fpreparerecv(soap, soap->buf, ret))) + return soap->error; +#endif +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { register int r; + memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); + soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx); + soap->d_stream.avail_in = (unsigned int)ret; + soap->d_stream.next_out = (Byte*)soap->buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + r = inflate(&soap->d_stream, Z_NO_FLUSH); + if (r == Z_OK || r == Z_STREAM_END) + { soap->bufidx = 0; + soap->z_buflen = soap->buflen; + soap->buflen = ret = SOAP_BUFLEN - soap->d_stream.avail_out; + if (soap->zlib_in == SOAP_ZLIB_GZIP) + soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %u bytes\n", (unsigned int)ret)); + if (!ret) + goto zlib_again; + if (r == Z_STREAM_END) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out)); + soap->z_ratio_in = (float)soap->d_stream.total_in / (float)soap->d_stream.total_out; + soap->d_stream.next_out = Z_NULL; + } + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to inflate: (%d) %s\n", r, soap->d_stream.msg?soap->d_stream.msg:"")); + soap->d_stream.next_out = Z_NULL; + soap->error = SOAP_ZLIB_ERROR; + return EOF; + } + } +#endif + soap->count += ret; + return !ret; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv(struct soap *soap) +{ +#ifndef WITH_LEANER + if (soap->mode & SOAP_ENC_DIME) + { if (soap->dime.buflen) + { char *s; + int i; + unsigned char tmp[12]; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME hdr for chunked DIME is in buffer\n")); + soap->count += soap->dime.buflen - soap->buflen; + soap->buflen = soap->dime.buflen; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Skip padding (%ld bytes)\n", -(long)soap->dime.size&3)); + for (i = -(long)soap->dime.size&3; i > 0; i--) + { soap->bufidx++; + if (soap->bufidx >= soap->buflen) + if (soap_recv_raw(soap)) + return EOF; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME hdr for next chunk\n")); + s = (char*)tmp; + for (i = 12; i > 0; i--) + { *s++ = soap->buf[soap->bufidx++]; + if (soap->bufidx >= soap->buflen) + if (soap_recv_raw(soap)) + return EOF; + } + soap->dime.flags = tmp[0] & 0x7; + soap->dime.size = ((size_t)tmp[8] << 24) | ((size_t)tmp[9] << 16) | ((size_t)tmp[10] << 8) | ((size_t)tmp[11]); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME chunk (%u bytes)\n", (unsigned int)soap->dime.size)); + if (soap->dime.flags & SOAP_DIME_CF) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "More chunking\n")); + soap->dime.chunksize = soap->dime.size; + if (soap->buflen - soap->bufidx >= soap->dime.size) + { soap->dime.buflen = soap->buflen; + soap->buflen = soap->bufidx + soap->dime.chunksize; + } + else + soap->dime.chunksize -= soap->buflen - soap->bufidx; + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Last chunk\n")); + soap->dime.buflen = 0; + soap->dime.chunksize = 0; + } + soap->count = soap->buflen - soap->bufidx; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%u bytes remaining\n", (unsigned int)soap->count)); + return SOAP_OK; + } + if (soap->dime.chunksize) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get next DIME hdr for chunked DIME (%u bytes chunk)\n", (unsigned int)soap->dime.chunksize)); + if (soap_recv_raw(soap)) + return EOF; + if (soap->buflen - soap->bufidx >= soap->dime.chunksize) + { soap->dime.buflen = soap->buflen; + soap->count -= soap->buflen - soap->bufidx - soap->dime.chunksize; + soap->buflen = soap->bufidx + soap->dime.chunksize; + } + else + soap->dime.chunksize -= soap->buflen - soap->bufidx; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%lu bytes remaining, count=%u\n", (unsigned long)(soap->buflen-soap->bufidx), (unsigned int)soap->count)); + return SOAP_OK; + } + } +#endif + return soap_recv_raw(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +soap_wchar +SOAP_FMAC2 +soap_getchar(struct soap *soap) +{ register soap_wchar c; + c = soap->ahead; + if (c) + { if (c != EOF) + soap->ahead = 0; + return c; + } + return soap_get1(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +const struct soap_code_map* +SOAP_FMAC2 +soap_code(const struct soap_code_map *map, const char *str) +{ if (str) + { while (map->string) + { if (!strcmp(str, map->string)) /* case sensitive */ + return map; + map++; + } + } + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +long +SOAP_FMAC2 +soap_int_code(const struct soap_code_map *map, const char *str, long other) +{ while (map->string) + { if (!soap_tag_cmp(str, map->string)) /* case insensitive */ + return map->code; + map++; + } + return other; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_str_code(const struct soap_code_map *map, long code) +{ while (map->code != code && map->string) + map++; + return map->string; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static soap_wchar +soap_char(struct soap *soap) +{ char tmp[8]; + register int i; + register soap_wchar c; + register char *s = tmp; + for (i = 0; i < 7; i++) + { c = soap_get1(soap); + if (c == ';' || (int)c == EOF) + break; + *s++ = (char)c; + } + *s = '\0'; + if (*tmp == '#') + { if (tmp[1] == 'x' || tmp[1] == 'X') + return soap_strtol(tmp + 2, NULL, 16); + return atol(tmp + 1); + } + if (!strcmp(tmp, "lt")) + return '<'; + if (!strcmp(tmp, "gt")) + return '>'; + if (!strcmp(tmp, "amp")) + return '&'; + if (!strcmp(tmp, "quot")) + return '"'; + if (!strcmp(tmp, "apos")) + return '\''; +#ifndef WITH_LEAN + return (soap_wchar)soap_int_code(html_entity_codes, tmp, SOAP_UNKNOWN_CHAR); +#else + return SOAP_UNKNOWN_CHAR; /* use this to represent unknown code */ +#endif +} +#endif + +/******************************************************************************/ +#ifdef WITH_LEAN +soap_wchar +soap_get0(struct soap *soap) +{ if (soap->bufidx >= soap->buflen && soap_recv(soap)) + return EOF; + return (unsigned char)soap->buf[soap->bufidx]; +} +#endif + +/******************************************************************************/ +#ifdef WITH_LEAN +soap_wchar +soap_get1(struct soap *soap) +{ if (soap->bufidx >= soap->buflen && soap_recv(soap)) + return EOF; + return (unsigned char)soap->buf[soap->bufidx++]; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +soap_wchar +SOAP_FMAC2 +soap_get(struct soap *soap) +{ register soap_wchar c; + c = soap->ahead; + if (c) + { if (c != EOF) + soap->ahead = 0; + } + else + c = soap_get1(soap); + for (;;) + { if (soap->cdata) + { if (c == ']') + { c = soap_get1(soap); + if (c == ']') + { soap->cdata = 0; + soap_get1(soap); /* skip > */ + c = soap_get1(soap); + } + else + { soap_revget1(soap); + return ']'; + } + } + else + return c; + } + switch (c) + { case '<': + do c = soap_get1(soap); + while (soap_blank(c)); + if (c == '!' || c == '?' || c == '%') + { register int k = 1; + if (c == '!') + { c = soap_get1(soap); + if (c == '[') + { do c = soap_get1(soap); + while ((int)c != EOF && c != '['); + if ((int)c == EOF) + break; + soap->cdata = 1; + c = soap_get1(soap); + continue; + } + if (c == '-' && (c = soap_get1(soap)) == '-') + { do + { c = soap_get1(soap); + if (c == '-' && (c = soap_get1(soap)) == '-') + break; + } while ((int)c != EOF); + } + } + else if (c == '?') + c = soap_get_pi(soap); + while ((int)c != EOF) + { if (c == '<') + k++; + else if (c == '>') + { if (--k <= 0) + break; + } + c = soap_get1(soap); + } + if ((int)c == EOF) + break; + c = soap_get1(soap); + continue; + } + if (c == '/') + return SOAP_TT; + soap_revget1(soap); + return SOAP_LT; + case '>': + return SOAP_GT; + case '"': + return SOAP_QT; + case '\'': + return SOAP_AP; + case '&': + return soap_char(soap) | 0x80000000; + } + break; + } + return c; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static soap_wchar +soap_get_pi(struct soap *soap) +{ char buf[64]; + register char *s = buf; + register int i = sizeof(buf); + register soap_wchar c = soap_getchar(soap); + /* This is a quick way to parse XML PI and we could use a callback instead to + * enable applications to intercept processing instructions */ + while ((int)c != EOF && c != '?') + { if (--i > 0) + { if (soap_blank(c)) + c = ' '; + *s++ = (char)c; + } + c = soap_getchar(soap); + } + *s = '\0'; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "XML PI \n", buf)); + if (!strncmp(buf, "xml ", 4)) + { s = strstr(buf, " encoding="); + if (s && s[10]) + { if (!soap_tag_cmp(s + 11, "iso-8859-1*") + || !soap_tag_cmp(s + 11, "latin1*")) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to latin1 encoding\n")); + soap->mode |= SOAP_ENC_LATIN; + } + else if (!soap_tag_cmp(s + 11, "utf-8*")) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to utf-8 encoding\n")); + soap->mode &= ~SOAP_ENC_LATIN; + } + } + } + if ((int)c != EOF) + c = soap_getchar(soap); + return c; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_move(struct soap *soap, long n) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving %ld bytes forward\n", (long)n)); + for (; n > 0; n--) + if ((int)soap_getchar(soap) == EOF) + return SOAP_EOF; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_tell(struct soap *soap) +{ return soap->count - soap->buflen + soap->bufidx - (soap->ahead != 0); +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_pututf8(struct soap *soap, register unsigned long c) +{ char tmp[16]; + if (c > 0 && c < 0x80) + { *tmp = (char)c; + return soap_send_raw(soap, tmp, 1); + } +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { register char *t = tmp; + if (c < 0x0800) + *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); + else + { if (c < 0x010000) + *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + else + { if (c < 0x200000) + *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + else + { if (c < 0x04000000) + *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + else + { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + } + *t++ = (char)(0x80 | (c & 0x3F)); + *t = '\0'; + } + else +#endif + sprintf(tmp, "&#%lu;", c); + return soap_send(soap, tmp); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +soap_wchar +SOAP_FMAC2 +soap_getutf8(struct soap *soap) +{ register soap_wchar c, c1, c2, c3, c4; + c = soap->ahead; + if (c > 0xFF) + { soap->ahead = 0; + return c; + } +again: + c = soap_get(soap); + if (c < 0x80 || (soap->mode & SOAP_ENC_LATIN)) + return c; + c1 = soap_get1(soap); + if (c1 < 0x80) + { soap_revget1(soap); /* doesn't look like this is UTF8 */ + return c; + } + c1 &= 0x3F; + if (c < 0xE0) + return ((soap_wchar)(c & 0x1F) << 6) | c1; + c2 = (soap_wchar)soap_get1(soap) & 0x3F; + if (c == 0xEF && c1 == 0x3B && c2 == 0x3F) /* ignore UTF-8 BOM */ + goto again; + if (c < 0xF0) + return ((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2; + c3 = (soap_wchar)soap_get1(soap) & 0x3F; + if (c < 0xF8) + return ((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3; + c4 = (soap_wchar)soap_get1(soap) & 0x3F; + if (c < 0xFC) + return ((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4; + return ((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(soap_get1(soap) & 0x3F); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_puthex(struct soap *soap, const unsigned char *s, int n) +{ char d[2]; + register int i; +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { if (!(soap->dom->data = soap_s2hex(soap, s, NULL, n))) + return soap->error; + return SOAP_OK; + } +#endif + for (i = 0; i < n; i++) + { register int m = *s++; + d[0] = (char)((m >> 4) + (m > 159 ? '7' : '0')); + m &= 0x0F; + d[1] = (char)(m + (m > 9 ? '7' : '0')); + if (soap_send_raw(soap, d, 2)) + return soap->error; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +unsigned char* +SOAP_FMAC2 +soap_gethex(struct soap *soap, int *n) +{ +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { soap->dom->data = soap_string_in(soap, 0, -1, -1); + return (unsigned char*)soap_hex2s(soap, soap->dom->data, NULL, 0, n); + } +#endif +#ifdef WITH_FAST + soap->labidx = 0; + for (;;) + { register char *s; + register int i, k; + if (soap_append_lab(soap, NULL, 0)) + return NULL; + s = soap->labbuf + soap->labidx; + k = soap->lablen - soap->labidx; + soap->labidx = soap->lablen; + for (i = 0; i < k; i++) + { register char d1, d2; + register soap_wchar c; + c = soap_get(soap); + if (soap_isxdigit(c)) + { d1 = (char)c; + c = soap_get(soap); + if (soap_isxdigit(c)) + d2 = (char)c; + else + { soap->error = SOAP_TYPE; + return NULL; + } + } + else + { unsigned char *p; + soap_unget(soap, c); + if (n) + *n = (int)(soap->lablen - k + i); + p = (unsigned char*)soap_malloc(soap, soap->lablen - k + i); + if (p) + memcpy(p, soap->labbuf, soap->lablen - k + i); + return p; + } + *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'); + } + } +#else + if (soap_new_block(soap)) + return NULL; + for (;;) + { register int i; + register char *s = (char*)soap_push_block(soap, SOAP_BLKLEN); + if (!s) + { soap_end_block(soap); + return NULL; + } + for (i = 0; i < SOAP_BLKLEN; i++) + { register char d1, d2; + register soap_wchar c = soap_get(soap); + if (soap_isxdigit(c)) + { d1 = (char)c; + c = soap_get(soap); + if (soap_isxdigit(c)) + d2 = (char)c; + else + { soap_end_block(soap); + soap->error = SOAP_TYPE; + return NULL; + } + } + else + { unsigned char *p; + soap_unget(soap, c); + if (n) + *n = soap_size_block(soap, i); + p = (unsigned char*)soap_save_block(soap, NULL, 0); + return p; + } + *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'); + } + } +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putbase64(struct soap *soap, const unsigned char *s, int n) +{ register int i; + register unsigned long m; + char d[4]; + if (!s) + return SOAP_OK; +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { if (!(soap->dom->data = soap_s2base64(soap, s, NULL, n))) + return soap->error; + return SOAP_OK; + } +#endif + for (; n > 2; n -= 3, s += 3) + { m = s[0]; + m = (m << 8) | s[1]; + m = (m << 8) | s[2]; + for (i = 4; i > 0; m >>= 6) + d[--i] = soap_base64o[m & 0x3F]; + if (soap_send_raw(soap, d, 4)) + return soap->error; + } + if (n > 0) + { m = 0; + for (i = 0; i < n; i++) + m = (m << 8) | *s++; + for (; i < 3; i++) + m <<= 8; + for (i++; i > 0; m >>= 6) + d[--i] = soap_base64o[m & 0x3F]; + for (i = 3; i > n; i--) + d[i] = '='; + if (soap_send_raw(soap, d, 4)) + return soap->error; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +unsigned char* +SOAP_FMAC2 +soap_getbase64(struct soap *soap, int *n, int malloc_flag) +{ +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { soap->dom->data = soap_string_in(soap, 0, -1, -1); + return (unsigned char*)soap_base642s(soap, soap->dom->data, NULL, 0, n); + } +#endif +#ifdef WITH_FAST + soap->labidx = 0; + for (;;) + { register int i, k; + register char *s; + if (soap_append_lab(soap, NULL, 2)) + return NULL; + s = soap->labbuf + soap->labidx; + k = soap->lablen - soap->labidx; + soap->labidx = 3 * (soap->lablen / 3); + if (!s) + return NULL; + for (i = 0; i < k - 2; i += 3) + { register unsigned long m = 0; + register int j = 0; + do + { register soap_wchar c = soap_get(soap); + if (c == '=' || c < 0) + { unsigned char *p; + switch (j) + { case 2: + *s++ = (char)((m >> 4) & 0xFF); + i++; + break; + case 3: + *s++ = (char)((m >> 10) & 0xFF); + *s++ = (char)((m >> 2) & 0xFF); + i += 2; + } + if (n) + *n = (int)(soap->lablen - k + i); + p = (unsigned char*)soap_malloc(soap, soap->lablen - k + i); + if (p) + memcpy(p, soap->labbuf, soap->lablen - k + i); + if (c >= 0) + { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT) + ; + } + soap_unget(soap, c); + return p; + } + c -= '+'; + if (c >= 0 && c <= 79) + { m = (m << 6) + soap_base64i[c]; + j++; + } + } while (j < 4); + *s++ = (char)((m >> 16) & 0xFF); + *s++ = (char)((m >> 8) & 0xFF); + *s++ = (char)(m & 0xFF); + } + } +#else + if (soap_new_block(soap)) + return NULL; + for (;;) + { register int i; + register char *s = (char*)soap_push_block(soap, 3 * SOAP_BLKLEN); /* must be multiple of 3 */ + if (!s) + { soap_end_block(soap); + return NULL; + } + for (i = 0; i < SOAP_BLKLEN; i++) + { register unsigned long m = 0; + register int j = 0; + do + { register soap_wchar c = soap_get(soap); + if (c == '=' || c < 0) + { unsigned char *p; + i *= 3; + switch (j) + { case 2: + *s++ = (char)((m >> 4) & 0xFF); + i++; + break; + case 3: + *s++ = (char)((m >> 10) & 0xFF); + *s++ = (char)((m >> 2) & 0xFF); + i += 2; + } + if (n) + *n = (int)soap_size_block(soap, i); + p = (unsigned char*)soap_save_block(soap, NULL, 0); + if (c >= 0) + { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT) + ; + } + soap_unget(soap, c); + return p; + } + c -= '+'; + if (c >= 0 && c <= 79) + { m = (m << 6) + soap_base64i[c]; + j++; + } + } while (j < 4); + *s++ = (char)((m >> 16) & 0xFF); + *s++ = (char)((m >> 8) & 0xFF); + *s++ = (char)(m & 0xFF); + } + } +#endif +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_xop_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options) +{ /* Check MTOM xop:Include element (within hex/base64Binary) */ + /* TODO: this code to be obsoleted with new import/xop.h conventions */ + int body = soap->body; /* should save type too? */ + if (!soap_peek_element(soap)) + { if (!soap_element_begin_in(soap, "xop:Include", 0) && *soap->href) + { if (soap_dime_forward(soap, ptr, size, id, type, options)) + return soap->error; + } + if (soap->body && soap_element_end_in(soap, NULL)) + return soap->error; + } + soap->body = body; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_dime_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options) +{ struct soap_xlist *xp = (struct soap_xlist*)SOAP_MALLOC(soap, sizeof(struct soap_xlist)); + *ptr = NULL; + *size = 0; + *id = soap_strdup(soap, soap->href); + *type = NULL; + *options = NULL; + if (!xp) + return soap->error = SOAP_EOM; + xp->next = soap->xlist; + xp->ptr = ptr; + xp->size = size; + xp->id = *id; + xp->type = type; + xp->options = options; + soap->xlist = xp; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_strdup(struct soap *soap, const char *s) +{ char *t = NULL; + if (s && (t = (char*)soap_malloc(soap, strlen(s) + 1))) + strcpy(t, s); + return t; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_new_block(struct soap *soap) +{ struct soap_blist *p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New block sequence (prev=%p)\n", soap->blist)); + if (!(p = (struct soap_blist*)SOAP_MALLOC(soap, sizeof(struct soap_blist)))) + return SOAP_EOM; + p->next = soap->blist; + p->ptr = NULL; + p->size = 0; + soap->blist = p; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_push_block(struct soap *soap, size_t n) +{ char *p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push block of %u bytes (%u bytes total)\n", (unsigned int)n, (unsigned int)soap->blist->size + (unsigned int)n)); + if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(char*) + sizeof(size_t)))) + { soap->error = SOAP_EOM; + return NULL; + } + *(char**)p = soap->blist->ptr; + *(size_t*)(p + sizeof(char*)) = n; + soap->blist->ptr = p; + soap->blist->size += n; + return p + sizeof(char*) + sizeof(size_t); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_pop_block(struct soap *soap) +{ char *p; + if (!soap->blist->ptr) + return; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop block\n")); + p = soap->blist->ptr; + soap->blist->size -= *(size_t*)(p + sizeof(char*)); + soap->blist->ptr = *(char**)p; + SOAP_FREE(soap, p); +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static void +soap_update_ptrs(struct soap *soap, char *start, char *end, long offset) +{ int i; + register struct soap_ilist *ip; + register struct soap_flist *fp; +#ifndef WITH_LEANER + register struct soap_xlist *xp; +#endif + register void *p, **q; + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { if (ip->ptr && (char*)ip->ptr >= start && (char*)ip->ptr < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", ip->id, ip->ptr, (char*)ip->ptr + offset)); + ip->ptr = (char*)ip->ptr + offset; + } + for (q = &ip->link; q; q = (void**)p) + { p = *q; + if (p && (char*)p >= start && (char*)p < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Link update id='%s' %p\n", ip->id, p)); + *q = (char*)p + offset; + } + } + for (q = &ip->copy; q; q = (void**)p) + { p = *q; + if (p && (char*)p >= start && (char*)p < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy chain update id='%s' %p\n", ip->id, p)); + *q = (char*)p + offset; + } + } + for (fp = ip->flist; fp; fp = fp->next) + { if ((char*)fp->ptr >= start && (char*)fp->ptr < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy list update id='%s' %p\n", ip->id, fp)); + fp->ptr = (char*)fp->ptr + offset; + } + } + } + } +#ifndef WITH_LEANER + for (xp = soap->xlist; xp; xp = xp->next) + { if (xp->ptr && (char*)xp->ptr >= start && (char*)xp->ptr < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", xp->id?xp->id:"", xp->ptr, (char*)xp->ptr + offset)); + xp->ptr = (unsigned char**)((char*)xp->ptr + offset); + xp->size = (int*)((char*)xp->size + offset); + xp->type = (char**)((char*)xp->type + offset); + xp->options = (char**)((char*)xp->options + offset); + } + } +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static int +soap_has_copies(struct soap *soap, register const char *start, register const char *end) +{ register int i; + register struct soap_ilist *ip; + register struct soap_flist *fp; + register const char *p; + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { for (p = (const char*)ip->copy; p; p = *(const char**)p) + if (p >= start && p < end) + return SOAP_ERR; + for (fp = ip->flist; fp; fp = fp->next) + if ((const char*)fp->ptr >= start && (const char*)fp->ptr < end) + return SOAP_ERR; + } + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_resolve(struct soap *soap) +{ register int i; + register struct soap_ilist *ip; + register struct soap_flist *fp; + short flag; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data\n")); + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { if (ip->ptr) + { register void *p, **q, *r; + q = (void**)ip->link; + ip->link = NULL; + r = ip->ptr; + DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing link chain to resolve id='%s'\n", ip->id)); + while (q) + { p = *q; + *q = r; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "... link %p -> %p\n", q, r)); + q = (void**)p; + } + } + else if (*ip->id == '#') + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Missing data for id='%s'\n", ip->id)); + strcpy(soap->id, ip->id + 1); + return soap->error = SOAP_MISSING_ID; + } + } + } + do + { flag = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution phase\n")); + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { if (ip->ptr && !soap_has_copies(soap, (const char*)ip->ptr, (const char*)ip->ptr + ip->size)) + { if (ip->copy) + { register void *p, **q = (void**)ip->copy; + DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing copy chain to resolve id='%s'\n", ip->id)); + ip->copy = NULL; + do + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... copy %p -> %p (%u bytes)\n", ip->ptr, q, (unsigned int)ip->size)); + p = *q; + memcpy(q, ip->ptr, ip->size); + q = (void**)p; + } while (q); + flag = 1; + } + for (fp = ip->flist; fp; fp = ip->flist) + { register unsigned int k = fp->level; + register void *p = ip->ptr; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data type=%d location=%p level=%u,%u id='%s'\n", ip->type, p, ip->level, fp->level, ip->id)); + while (ip->level < k) + { register void **q = (void**)soap_malloc(soap, sizeof(void*)); + if (!q) + return soap->error; + *q = p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level, new location=%p holds=%p...\n", q, *q)); + p = (void*)q; + k--; + } + if (fp->fcopy) + fp->fcopy(soap, ip->type, fp->type, fp->ptr, p, ip->size); + else + soap_fcopy(soap, ip->type, fp->type, fp->ptr, p, ip->size); + ip->flist = fp->next; + SOAP_FREE(soap, fp); + flag = 1; + } + } + } + } + } while (flag); +#ifdef SOAP_DEBUG + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { if (ip->copy || ip->flist) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution error: forwarded data for id='%s' could not be propagated, please report this problem to the developers\n", ip->id)); + } + } + } +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution done\n")); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_size_block(struct soap *soap, size_t n) +{ if (soap->blist->ptr) + { soap->blist->size -= *(size_t*)(soap->blist->ptr + sizeof(char*)) - n; + *(size_t*)(soap->blist->ptr + sizeof(char*)) = n; + } + return soap->blist->size; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_first_block(struct soap *soap) +{ char *p, *q, *r; + p = soap->blist->ptr; + if (!p) + return NULL; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "First block\n")); + r = NULL; + do + { q = *(char**)p; + *(char**)p = r; + r = p; + p = q; + } while (p); + soap->blist->ptr = r; + return r + sizeof(char*) + sizeof(size_t); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_next_block(struct soap *soap) +{ char *p; + p = soap->blist->ptr; + if (p) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Next block\n")); + soap->blist->ptr = *(char**)p; + SOAP_FREE(soap, p); + if (soap->blist->ptr) + return soap->blist->ptr + sizeof(char*) + sizeof(size_t); + } + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_block_size(struct soap *soap) +{ return *(size_t*)(soap->blist->ptr + sizeof(char*)); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_end_block(struct soap *soap) +{ struct soap_blist *bp; + char *p, *q; + bp = soap->blist; + if (bp) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of block sequence, free all remaining blocks\n")); + for (p = bp->ptr; p; p = q) + { q = *(char**)p; + SOAP_FREE(soap, p); + } + soap->blist = bp->next; + SOAP_FREE(soap, bp); + } + DBGLOG(TEST, if (soap->blist) SOAP_MESSAGE(fdebug, "Restore previous block sequence\n")); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_save_block(struct soap *soap, char *p, int flag) +{ register size_t n; + register char *q, *s; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Save all blocks in contiguous memory space of %u bytes (%p->%p)\n", (unsigned int)soap->blist->size, soap->blist->ptr, p)); + if (soap->blist->size) + { if (!p) + p = (char*)soap_malloc(soap, soap->blist->size); + if (p) + { for (s = p, q = soap_first_block(soap); q; q = soap_next_block(soap)) + { n = soap_block_size(soap); +#ifndef WITH_NOIDREF + if (flag) + soap_update_ptrs(soap, q, q + n, (long)s - (long)q); /* pointers s and q may or may not be related */ +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy %u bytes from %p to %p\n", (unsigned int)n, q, s)); + memcpy(s, q, n); + s += n; + } + } + else + soap->error = SOAP_EOM; + } + soap_end_block(soap); + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putsize(struct soap *soap, const char *type, int size) +{ return soap_putsizes(soap, type, &size, 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putsizes(struct soap *soap, const char *type, const int *size, int dim) +{ return soap_putsizesoffsets(soap, type, size, NULL, dim); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putsizesoffsets(struct soap *soap, const char *type, const int *size, const int *offset, int dim) +{ int i; + if (!type) + return NULL; + if (soap->version == 2) + { sprintf(soap->type, "%s[%d", type, size[0]); + for (i = 1; i < dim; i++) + sprintf(soap->type + strlen(soap->type), " %d", size[i]); + } + else + { if (offset) + { sprintf(soap->type, "%s[%d", type, size[0] + offset[0]); + for (i = 1; i < dim; i++) + sprintf(soap->type + strlen(soap->type), ",%d", size[i] + offset[i]); + } + else + { sprintf(soap->type, "%s[%d", type, size[0]); + for (i = 1; i < dim; i++) + sprintf(soap->type + strlen(soap->type), ",%d", size[i]); + } + strcat(soap->type, "]"); + } + return soap->type; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putoffset(struct soap *soap, int offset) +{ return soap_putoffsets(soap, &offset, 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putoffsets(struct soap *soap, const int *offset, int dim) +{ register int i; + sprintf(soap->arrayOffset, "[%d", offset[0]); + for (i = 1; i < dim; i++) + sprintf(soap->arrayOffset + strlen(soap->arrayOffset), ",%d", offset[i]); + strcat(soap->arrayOffset, "]"); + return soap->arrayOffset; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_size(const int *size, int dim) +{ register int i, n = size[0]; + for (i = 1; i < dim; i++) + n *= size[i]; + return n; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getoffsets(const char *attr, const int *size, int *offset, int dim) +{ register int i, j = 0; + if (offset) + for (i = 0; i < dim && attr && *attr; i++) + { attr++; + j *= size[i]; + j += offset[i] = (int)atol(attr); + attr = strchr(attr, ','); + } + else + for (i = 0; i < dim && attr && *attr; i++) + { attr++; + j *= size[i]; + j += (int)atol(attr); + attr = strchr(attr, ','); + } + return j; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getsize(const char *attr1, const char *attr2, int *j) +{ register int n, k; + char *s; + *j = 0; + if (!*attr1) + return -1; + if (*attr1 == '[') + attr1++; + n = 1; + for (;;) + { k = (int)soap_strtol(attr1, &s, 10); + n *= k; + if (k < 0 || n > SOAP_MAXARRAYSIZE || s == attr1) + return -1; + attr1 = strchr(s, ','); + if (!attr1) + attr1 = strchr(s, ' '); + if (attr2 && *attr2) + { attr2++; + *j *= k; + k = (int)soap_strtol(attr2, &s, 10); + *j += k; + if (k < 0) + return -1; + attr2 = s; + } + if (!attr1) + break; + attr1++; + } + return n - *j; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getsizes(const char *attr, int *size, int dim) +{ register int i, k, n; + if (!*attr) + return -1; + i = strlen(attr); + n = 1; + do + { for (i = i-1; i >= 0; i--) + if (attr[i] == '[' || attr[i] == ',' || attr[i] == ' ') + break; + k = (int)atol(attr + i + 1); + n *= size[--dim] = k; + if (k < 0 || n > SOAP_MAXARRAYSIZE) + return -1; + } while (i >= 0 && attr[i] != '['); + return n; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getposition(const char *attr, int *pos) +{ register int i, n; + if (!*attr) + return -1; + n = 0; + i = 1; + do + { pos[n++] = (int)atol(attr + i); + while (attr[i] && attr[i] != ',' && attr[i] != ']') + i++; + if (attr[i] == ',') + i++; + } while (n < SOAP_MAXDIMS && attr[i] && attr[i] != ']'); + return n; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_push_namespace(struct soap *soap, const char *id, const char *ns) +{ register struct soap_nlist *np; + register struct Namespace *p; + register short i = -1; + register size_t n, k; + n = strlen(id); + k = strlen(ns) + 1; + p = soap->local_namespaces; + if (p) + { for (i = 0; p->id; p++, i++) + { if (p->ns && !strcmp(ns, p->ns)) + { if (p->out) + { SOAP_FREE(soap, p->out); + p->out = NULL; + } + break; + } + if (p->out) + { if (!strcmp(ns, p->out)) + break; + } + else if (p->in) + { if (!soap_tag_cmp(ns, p->in)) + { if ((p->out = (char*)SOAP_MALLOC(soap, k))) + strcpy(p->out, ns); + break; + } + } + } + if (!p || !p->id) + i = -1; + } + if (i >= 0) + k = 0; + np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k); + if (!np) + return soap->error = SOAP_EOM; + np->next = soap->nlist; + soap->nlist = np; + np->level = soap->level; + np->index = i; + strcpy(np->id, id); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push namespace binding (level=%u) '%s' '%s'\n", soap->level, id, ns)); + if (i < 0) + { np->ns = np->id + n + 1; + strcpy(np->ns, ns); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push NOT OK: no match found for '%s' in namespace mapping table (added to stack anyway)\n", ns)); + } + else + { np->ns = NULL; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push OK ('%s' matches '%s' in namespace table)\n", id, p->id)); + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_pop_namespace(struct soap *soap) +{ register struct soap_nlist *np; + while (soap->nlist && soap->nlist->level >= soap->level) + { np = soap->nlist->next; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Popped namespace binding (level=%u) '%s'\n", soap->level, soap->nlist->id)); + SOAP_FREE(soap, soap->nlist); + soap->nlist = np; + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_match_namespace(struct soap *soap, const char *id1, const char *id2, int n1, int n2) +{ register struct soap_nlist *np = soap->nlist; + while (np && (strncmp(np->id, id1, n1) || np->id[n1])) + np = np->next; + if (np) + { if (np->index < 0 + || (soap->local_namespaces[np->index].id + && (strncmp(soap->local_namespaces[np->index].id, id2, n2) + || soap->local_namespaces[np->index].id[n2]))) + return SOAP_NAMESPACE; + return SOAP_OK; + } + if (n1 == 3 && n1 == n2 && !strcmp(id1, "xml") && !strcmp(id1, id2)) + return SOAP_OK; + return SOAP_SYNTAX_ERROR; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_current_namespace(struct soap *soap, const char *tag) +{ register struct soap_nlist *np; + register const char *s; + np = soap->nlist; + if (!(s = strchr(tag, ':'))) + { while (np && *np->id) /* find default namespace, if present */ + np = np->next; + } + else + { while (np && (strncmp(np->id, tag, s - tag) || np->id[s - tag])) + np = np->next; + if (!np) + soap->error = SOAP_NAMESPACE; + } + if (np) + { if (np->index >= 0) + return soap->namespaces[np->index].ns; + if (np->ns) + return soap_strdup(soap, np->ns); + } + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_tag_cmp(const char *s, const char *t) +{ for (;;) + { register int c1 = *s; + register int c2 = *t; + if (!c1 || c1 == '"') + break; + if (c2 != '-') + { if (c1 != c2) + { if (c1 >= 'A' && c1 <= 'Z') + c1 += 'a' - 'A'; + if (c2 >= 'A' && c2 <= 'Z') + c2 += 'a' - 'A'; + } + if (c1 != c2) + { if (c2 != '*') + return 1; + c2 = *++t; + if (!c2) + return 0; + if (c2 >= 'A' && c2 <= 'Z') + c2 += 'a' - 'A'; + for (;;) + { c1 = *s; + if (!c1 || c1 == '"') + break; + if (c1 >= 'A' && c1 <= 'Z') + c1 += 'a' - 'A'; + if (c1 == c2 && !soap_tag_cmp(s + 1, t + 1)) + return 0; + s++; + } + break; + } + } + s++; + t++; + } + if (*t == '*' && !t[1]) + return 0; + return *t; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_match_tag(struct soap *soap, const char *tag1, const char *tag2) +{ register const char *s, *t; + if (!tag1 || !tag2 || !*tag2) + return SOAP_OK; + s = strchr(tag1, ':'); + t = strchr(tag2, ':'); + if (t) + { if (s) + { if (t[1] && SOAP_STRCMP(s + 1, t + 1)) + return SOAP_TAG_MISMATCH; + if (t != tag2 && soap_match_namespace(soap, tag1, tag2, s - tag1, t - tag2)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2)); + return SOAP_TAG_MISMATCH; + } + } + else if (SOAP_STRCMP(tag1, t + 1)) + return SOAP_TAG_MISMATCH; + else if (t != tag2 && soap_match_namespace(soap, tag1, tag2, 0, t - tag2)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2)); + return SOAP_TAG_MISMATCH; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags and (default) namespaces match: '%s' '%s'\n", tag1, tag2)); + return SOAP_OK; + } + if (s) + { if (SOAP_STRCMP(s + 1, tag2)) + return SOAP_TAG_MISMATCH; + } + else if (SOAP_STRCMP(tag1, tag2)) + return SOAP_TAG_MISMATCH; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags match: '%s' '%s'\n", tag1, tag2)); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_match_array(struct soap *soap, const char *type) +{ if (*soap->arrayType) + if (soap_match_tag(soap, soap->arrayType, type) + && soap_match_tag(soap, soap->arrayType, "xsd:anyType") + && soap_match_tag(soap, soap->arrayType, "xsd:ur-type") + ) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array type mismatch: '%s' '%s'\n", soap->arrayType, type)); + return SOAP_TAG_MISMATCH; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ + +#ifdef WITH_OPENSSL +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_rand() +{ unsigned char buf[4]; + ssl_init(); + RAND_pseudo_bytes(buf, 4); + return *(int*)buf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_ssl_server_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *password, const char *cafile, const char *capath, const char *dhfile, const char *randfile, const char *sid) +{ int err; + soap->keyfile = keyfile; + soap->password = password; + soap->cafile = cafile; + soap->capath = capath; + if (dhfile) + { soap->dhfile = dhfile; + soap->rsa = 0; + } + else + { soap->dhfile = NULL; + soap->rsa = 1; + } + soap->randfile = randfile; + soap->require_client_auth = (flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION); + if (!(err = soap->fsslauth(soap))) + { if (sid) + SSL_CTX_set_session_id_context(soap->ctx, (unsigned char*)sid, strlen(sid)); + } + return err; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_ssl_client_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *password, const char *cafile, const char *capath, const char *randfile) +{ soap->keyfile = keyfile; + soap->password = password; + soap->cafile = cafile; + soap->capath = capath; + soap->dhfile = NULL; + soap->rsa = 0; + soap->randfile = randfile; + soap->require_server_auth = (flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION); + return soap->fsslauth(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +static void +ssl_init() +{ static int done = 0; + if (!done) + { done = 1; + SSL_library_init(); +#ifndef WITH_LEAN + SSL_load_error_strings(); +#endif + if (!RAND_load_file("/dev/urandom", 1024)) + { char buf[1024]; + RAND_seed(buf, sizeof(buf)); + while (!RAND_status()) + { int r = rand(); + RAND_seed(&r, sizeof(int)); + } + } + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static const char * +ssl_error(struct soap *soap, int ret) +{ int err = SSL_get_error(soap->ssl, ret); + const char *msg = soap_str_code(h_ssl_error_codes, err); + if (msg) + strcpy(soap->msgbuf, msg); + else + return ERR_error_string(err, soap->msgbuf); + if (ERR_peek_error()) + { unsigned long r; + strcat(soap->msgbuf, "\n"); + while ((r = ERR_get_error())) + ERR_error_string_n(r, soap->msgbuf + strlen(soap->msgbuf), sizeof(soap->msgbuf) - strlen(soap->msgbuf)); + } + else + { switch (ret) + { case 0: + strcpy(soap->msgbuf, "EOF was observed that violates the protocol. The client probably provided invalid authentication information."); + break; + case -1: + sprintf(soap->msgbuf, "Error observed by underlying BIO: %s", strerror(errno)); + break; + } + } + return soap->msgbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +ssl_password(char *buf, int num, int rwflag, void *userdata) +{ if (num < (int)strlen((char*)userdata) + 1) + return 0; + return strlen(strcpy(buf, (char*)userdata)); +} +#endif + +/******************************************************************************/ +/* This callback is included for future references. It should not be deleted +#ifndef PALM_2 +static DH * +ssl_tmp_dh(SSL *ssl, int is_export, int keylength) +{ static DH *dh512 = NULL; + static DH *dh1024 = NULL; + DH *dh; + switch (keylength) + { case 512: + if (!dh512) + { BIO *bio = BIO_new_file("dh512.pem", "r"); + if (bio) + { dh512 = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + return dh512; + } + } + else + return dh512; + default: + if (!dh1024) + { BIO *bio = BIO_new_file("dh1024.pem", "r"); + if (bio) + { dh1024 = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + } + } + dh = dh1024; + } + return dh; +} +#endif +*/ + +/******************************************************************************/ +#ifndef PALM_1 +static int +ssl_auth_init(struct soap *soap) +{ ssl_init(); + if (!soap->ctx) + { if (!(soap->ctx = SSL_CTX_new(SSLv23_method()))) + return soap_set_receiver_error(soap, "SSL error", "Can't setup context", SOAP_SSL_ERROR); + } + if (soap->randfile) + { if (!RAND_load_file(soap->randfile, -1)) + return soap_set_receiver_error(soap, "SSL error", "Can't load randomness", SOAP_SSL_ERROR); + } + if (soap->cafile || soap->capath) + { if (!SSL_CTX_load_verify_locations(soap->ctx, soap->cafile, soap->capath)) + return soap_set_receiver_error(soap, "SSL error", "Can't read CA file and directory", SOAP_SSL_ERROR); + if (soap->cafile && soap->require_client_auth) + SSL_CTX_set_client_CA_list(soap->ctx, SSL_load_client_CA_file(soap->cafile)); + } + if (!SSL_CTX_set_default_verify_paths(soap->ctx)) + return soap_set_receiver_error(soap, "SSL error", "Can't read default CA file and/or directory", SOAP_SSL_ERROR); +/* See below */ + if (soap->keyfile) + { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile)) + return soap_set_receiver_error(soap, "SSL error", "Can't read certificate key file", SOAP_SSL_ERROR); + if (soap->password) + { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password); + SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password); + } + if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM)) + return soap_set_receiver_error(soap, "SSL error", "Can't read key file", SOAP_SSL_ERROR); + } +/* Suggested alternative approach to check cafile first before the key file: + if (soap->password) + { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password); + SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password); + } + if (!soap->cafile || !SSL_CTX_use_certificate_chain_file(soap->ctx, soap->cafile)) + { if (soap->keyfile) + { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile)) + return soap_set_receiver_error(soap, "SSL error", "Can't read certificate or key file", SOAP_SSL_ERROR); + if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM)) + return soap_set_receiver_error(soap, "SSL error", "Can't read key file", SOAP_SSL_ERROR); + } + } +*/ + if (soap->rsa) + { RSA *rsa = RSA_generate_key(1024, RSA_F4, NULL, NULL); + if (!SSL_CTX_set_tmp_rsa(soap->ctx, rsa)) + { if (rsa) + RSA_free(rsa); + return soap_set_receiver_error(soap, "SSL error", "Can't set RSA key", SOAP_SSL_ERROR); + } + RSA_free(rsa); + } + else if (soap->dhfile) + { DH *dh = 0; + BIO *bio; + bio = BIO_new_file(soap->dhfile, "r"); + if (!bio) + return soap_set_receiver_error(soap, "SSL error", "Can't read DH file", SOAP_SSL_ERROR); + dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + if (SSL_CTX_set_tmp_dh(soap->ctx, dh) < 0) + { if (dh) + DH_free(dh); + return soap_set_receiver_error(soap, "SSL error", "Can't set DH parameters", SOAP_SSL_ERROR); + } + DH_free(dh); + } + SSL_CTX_set_options(soap->ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2); + SSL_CTX_set_verify(soap->ctx, soap->require_client_auth ? (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT) : soap->require_server_auth ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, soap->fsslverify); +#if (OPENSSL_VERSION_NUMBER < 0x00905100L) + SSL_CTX_set_verify_depth(soap->ctx, 1); +#else + SSL_CTX_set_verify_depth(soap->ctx, 9); +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +ssl_verify_callback(int ok, X509_STORE_CTX *store) +{ +#ifdef SOAP_DEBUG + if (!ok) + { char data[256]; + X509 *cert = X509_STORE_CTX_get_current_cert(store); + fprintf(stderr, "SSL verify error or warning with certificate at depth %d: %s\n", X509_STORE_CTX_get_error_depth(store), X509_verify_cert_error_string(X509_STORE_CTX_get_error(store))); + X509_NAME_oneline(X509_get_issuer_name(cert), data, sizeof(data)); + fprintf(stderr, "certificate issuer %s\n", data); + X509_NAME_oneline(X509_get_subject_name(cert), data, sizeof(data)); + fprintf(stderr, "certificate subject %s\n", data); + } +#endif + /* Note: return 1 to continue, but unsafe progress will be terminated by SSL */ + return ok; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_ssl_accept(struct soap *soap) +{ BIO *bio; + int i, r; + if (!soap_valid_socket(soap->socket)) + return soap_set_receiver_error(soap, "SSL error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR); + if (!soap->ctx && (soap->error = soap->fsslauth(soap))) + return SOAP_INVALID_SOCKET; + if (!soap->ssl) + { soap->ssl = SSL_new(soap->ctx); + if (!soap->ssl) + return soap_set_receiver_error(soap, "SSL error", "SSL_new() failed in soap_ssl_accept()", SOAP_SSL_ERROR); + } + else + SSL_clear(soap->ssl); + soap->imode |= SOAP_ENC_SSL; + soap->omode |= SOAP_ENC_SSL; +#if defined(WIN32) + { u_long nonblocking = 1; + ioctlsocket((SOAP_SOCKET)soap->socket, FIONBIO, &nonblocking); + } +#elif defined(VXWORKS) + { u_long nonblocking = 1; + ioctl((SOAP_SOCKET)soap->socket, FIONBIO, (int)&nonblocking); + } +#else + fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL)|O_NONBLOCK); +#endif + bio = BIO_new_socket((SOAP_SOCKET)soap->socket, BIO_NOCLOSE); + SSL_set_bio(soap->ssl, bio, bio); + i = 100; /* 100 * 0.1 ms retries */ + while ((r = SSL_accept(soap->ssl)) <= 0) + { int err = SSL_get_error(soap->ssl, r); + if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) + { struct timeval timeout; + fd_set fd; + if (i-- <= 0) + break; + timeout.tv_sec = 0; + timeout.tv_usec = 100000; + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->socket, &fd); + r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout); + if (r < 0 && soap_socket_errno != SOAP_EINTR) + { soap->errnum = soap_socket_errno; + return SOAP_EOF; + } + } + else + { soap->errnum = err; + break; + } + } +#if defined(WIN32) + { u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)soap->socket, FIONBIO, &blocking); + } +#elif defined(VXWORKS) + { u_long blocking = 0; + ioctl((SOAP_SOCKET)soap->socket, FIONBIO, (int)&blocking); + } +#else + fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL)&~O_NONBLOCK); +#endif + if (r <= 0) + { soap_set_receiver_error(soap, ssl_error(soap, r), "SSL_accept() failed in soap_ssl_accept()", SOAP_SSL_ERROR); + soap_closesock(soap); + return SOAP_SSL_ERROR; + } + if (soap->require_client_auth) + { X509 *peer; + int err; + if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK) + { soap_closesock(soap); + return soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL certificate presented by peer cannot be verified in soap_ssl_accept()", SOAP_SSL_ERROR); + } + peer = SSL_get_peer_certificate(soap->ssl); + if (!peer) + { soap_closesock(soap); + return soap_set_sender_error(soap, "SSL error", "No SSL certificate was presented by the peer in soap_ssl_accept()", SOAP_SSL_ERROR); + } + X509_free(peer); + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#endif /* WITH_OPENSSL */ + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_init(struct soap *soap) +{ soap->errmode = 1; +#ifdef WIN32 + if (tcp_done) + return 0; + else + { WSADATA w; + if (WSAStartup(MAKEWORD(1, 1), &w)) + return -1; + tcp_done = 1; + } +#endif + return 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_done(struct soap *soap) +{ +#ifdef SOAP_DEBUG + int i; +#endif + soap_free(soap); + while (soap->clist) + { struct soap_clist *p = soap->clist->next; + SOAP_FREE(soap, soap->clist); + soap->clist = p; + } + soap->keep_alive = 0; /* to force close the socket */ + soap_closesock(soap); +#ifdef WITH_COOKIES + soap_free_cookies(soap); +#endif + while (soap->plugins) + { register struct soap_plugin *p = soap->plugins->next; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Removing plugin '%s'\n", soap->plugins->id)); + if (soap->plugins->fcopy || !soap->copy) + soap->plugins->fdelete(soap, soap->plugins); + SOAP_FREE(soap, soap->plugins); + soap->plugins = p; + } + soap->fplugin = fplugin; +#ifndef WITH_NOHTTP + soap->fpost = http_post; + soap->fget = http_get; + soap->fform = NULL; + soap->fposthdr = http_post_header; + soap->fresponse = http_response; + soap->fparse = http_parse; + soap->fparsehdr = http_parse_header; +#endif +#ifndef WITH_NOIO +#ifndef WITH_IPV6 + soap->fresolve = tcp_gethost; +#else + soap->fresolve = NULL; +#endif + soap->faccept = tcp_accept; + soap->fopen = tcp_connect; + soap->fclose = tcp_disconnect; + soap->fclosesocket = tcp_closesocket; + soap->fshutdownsocket = tcp_shutdownsocket; + soap->fsend = fsend; + soap->frecv = frecv; + soap->fpoll = soap_poll; +#else + soap->fopen = NULL; + soap->fclose = NULL; + soap->fpoll = NULL; +#endif +#ifndef WITH_LEANER + soap->fprepareinit = NULL; + soap->fpreparesend = NULL; + soap->fpreparerecv = NULL; + soap->fpreparefinal = NULL; +#endif + soap->fseterror = NULL; + soap->fignore = NULL; + soap->fserveloop = NULL; +#ifdef WITH_OPENSSL + if (soap->session) + { SSL_SESSION_free(soap->session); + soap->session = NULL; + } +#endif + if (!soap->copy) + { if (soap_valid_socket(soap->master)) + { soap->fclosesocket(soap, (SOAP_SOCKET)soap->master); + soap->master = SOAP_INVALID_SOCKET; + } +#ifdef WITH_OPENSSL + if (soap->ctx) + { SSL_CTX_free(soap->ctx); + soap->ctx = NULL; + } +#endif + } +#ifdef SOAP_DEBUG + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free logfiles\n")); + for (i = 0; i < SOAP_MAXLOGS; i++) + { if (soap->logfile[i]) + { SOAP_FREE(soap, (void*)soap->logfile[i]); + soap->logfile[i] = NULL; + } + soap_close_logfile(soap, i); + } + soap_free_mht(soap); +#endif +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_cleanup(struct soap *soap) +{ soap_done(soap); +#ifdef WIN32 + if (!tcp_done) + return; + tcp_done = 0; + WSACleanup(); +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static const char* +tcp_error(struct soap *soap) +{ register const char *msg = NULL; + switch (soap->errmode) + { case 0: + msg = soap_strerror(soap); + break; + case 1: + msg = "WSAStartup failed"; + break; + case 2: + { +#ifndef WITH_LEAN + msg = soap_str_code(h_error_codes, soap->errnum); + if (!msg) +#endif + { sprintf(soap->msgbuf, "TCP/UDP IP error %d", soap->errnum); + msg = soap->msgbuf; + } + } + } + return msg; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static const char* +http_error(struct soap *soap, int status) +{ register const char *msg = SOAP_STR_EOS; +#ifndef WITH_LEAN + msg = soap_str_code(h_http_error_codes, status); + if (!msg) + msg = SOAP_STR_EOS; +#endif + return msg; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_IPV6 +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_gethost(struct soap *soap, const char *addr, struct in_addr *inaddr) +{ soap_int32 iadd = -1; + struct hostent hostent, *host = &hostent; +#ifdef VXWORKS + int hostint; + /* inet_addr(), and hostGetByName() expect "char *"; addr is a "const char *". */ + iadd = inet_addr((char*)addr); +#else +#if defined(_AIXVERSION_431) || defined(TRU64) + struct hostent_data ht_data; +#endif +#ifdef AS400 + iadd = inet_addr((void*)addr); +#else + iadd = inet_addr(addr); +#endif +#endif + if (iadd != -1) + { memcpy(inaddr, &iadd, sizeof(iadd)); + return SOAP_OK; + } +#if defined(__GLIBC__) + if (gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &host, &soap->errnum) < 0) + host = NULL; +#elif defined(_AIXVERSION_431) || defined(TRU64) + memset((void*)&ht_data, 0, sizeof(ht_data)); + if (gethostbyname_r(addr, &hostent, &ht_data) < 0) + { host = NULL; + soap->errnum = h_errno; + } +#elif defined(HAVE_GETHOSTBYNAME_R) + host = gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &soap->errnum); +#elif defined(VXWORKS) + /* If the DNS resolver library resolvLib has been configured in the vxWorks + * image, a query for the host IP address is sent to the DNS server, if the + * name was not found in the local host table. */ + hostint = hostGetByName((char*)addr); + if (hostint == ERROR) + { host = NULL; + soap->errnum = soap_errno; + } +#else +#ifdef AS400 + if (!(host = gethostbyname((void*)addr))) + soap->errnum = h_errno; +#else + if (!(host = gethostbyname(addr))) + soap->errnum = h_errno; +#endif +#endif + if (!host) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Host name not found\n")); + return SOAP_ERR; + } +#ifdef VXWORKS + inaddr->s_addr = hostint; +#else + memcpy(inaddr, host->h_addr, host->h_length); +#endif + return SOAP_OK; +} +#endif +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_connect(struct soap *soap, const char *endpoint, const char *host, int port) +{ +#ifdef WITH_IPV6 + struct addrinfo hints, *res, *ressave; + int err; +#endif + register int fd; +#ifndef WITH_LEAN + int len = SOAP_BUFLEN; + int set = 1; +#endif + if (soap_valid_socket(soap->socket)) + soap->fclosesocket(soap, (SOAP_SOCKET)soap->socket); + soap->socket = SOAP_INVALID_SOCKET; + if (tcp_init(soap)) + { soap->errnum = 0; + soap_set_sender_error(soap, tcp_error(soap), "TCP init failed in tcp_connect()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + soap->errmode = 0; +#ifdef WITH_IPV6 + memset((void*)&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + hints.ai_socktype = SOCK_DGRAM; + else +#endif + hints.ai_socktype = SOCK_STREAM; + soap->errmode = 2; + if (soap->proxy_host) + err = getaddrinfo(soap->proxy_host, soap_int2s(soap, soap->proxy_port), &hints, &res); + else + err = getaddrinfo(host, soap_int2s(soap, port), &hints, &res); + if (err) + { soap_set_sender_error(soap, gai_strerror(err), "getaddrinfo failed in tcp_connect()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + ressave = res; +again: + fd = (int)socket(res->ai_family, res->ai_socktype, res->ai_protocol); + soap->errmode = 0; +#else +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + fd = (int)socket(AF_INET, SOCK_DGRAM, 0); + else +#endif + fd = (int)socket(AF_INET, SOCK_STREAM, 0); +#endif + if (fd < 0) + { soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "socket failed in tcp_connect()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#ifdef SOCKET_CLOSE_ON_EXEC +#ifdef WIN32 +#ifndef UNDER_CE + SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0); +#endif +#else + fcntl(fd, F_SETFD, 1); +#endif +#endif +#ifndef WITH_LEAN + if (soap->connect_flags & SO_LINGER) + { struct linger linger; + memset((void*)&linger, 0, sizeof(linger)); + linger.l_onoff = 1; + linger.l_linger = 0; + if (setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger))) + { soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + } + if ((soap->connect_flags & ~SO_LINGER) && setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, soap->connect_flags & ~SO_LINGER, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "setsockopt failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + if (soap->keep_alive && setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + if (setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + if (setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } +#ifdef TCP_NODELAY + if (!(soap->omode & SOAP_IO_UDP) && setsockopt((SOAP_SOCKET)fd, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } +#endif +#endif + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Opening socket %d to host='%s' port=%d\n", fd, host, port)); +#ifndef WITH_IPV6 + soap->peerlen = sizeof(soap->peer); + memset((void*)&soap->peer, 0, sizeof(soap->peer)); + soap->peer.sin_family = AF_INET; + soap->errmode = 2; + if (soap->proxy_host) + { if (soap->fresolve(soap, soap->proxy_host, &soap->peer.sin_addr)) + { soap_set_sender_error(soap, tcp_error(soap), "get proxy host by name failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + soap->peer.sin_port = htons((short)soap->proxy_port); + } + else + { if (soap->fresolve(soap, host, &soap->peer.sin_addr)) + { soap_set_sender_error(soap, tcp_error(soap), "get host by name failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + soap->peer.sin_port = htons((short)port); + } + soap->errmode = 0; + if ((soap->omode & SOAP_IO_UDP)) + return fd; +#endif +#ifndef WITH_LEAN + if (soap->connect_timeout) +#if defined(WIN32) + { u_long nonblocking = 1; + ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &nonblocking); + } +#elif defined(VXWORKS) + { u_long nonblocking = 1; + ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&nonblocking)); /* modified to use fd */ + } +#else + fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)|O_NONBLOCK); +#endif + else +#if defined(WIN32) + { u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &blocking); + } +#elif defined(VXWORKS) + { u_long blocking = 0; + ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&blocking)); + } +#else + fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)&~O_NONBLOCK); +#endif +#endif + for (;;) + { +#ifdef WITH_IPV6 + if (connect((SOAP_SOCKET)fd, res->ai_addr, res->ai_addrlen)) +#else + if (connect((SOAP_SOCKET)fd, (struct sockaddr*)&soap->peer, sizeof(soap->peer))) +#endif + { +#ifndef WITH_LEAN + if (soap->connect_timeout && (soap_socket_errno == SOAP_EINPROGRESS || soap_socket_errno == SOAP_EWOULDBLOCK)) + { struct timeval timeout; + SOAP_SOCKLEN_T k; + fd_set fds; + if (soap->connect_timeout > 0) + { timeout.tv_sec = soap->connect_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->connect_timeout/1000000; + timeout.tv_usec = -soap->connect_timeout%1000000; + } + FD_ZERO(&fds); + FD_SET((SOAP_SOCKET)fd, &fds); + for (;;) + { int r = select((SOAP_SOCKET)(fd + 1), NULL, &fds, NULL, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n")); + soap_set_sender_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + if (soap_socket_errno != SOAP_EINTR) + { soap->errnum = soap_socket_errno; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); + soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + } + k = (SOAP_SOCKLEN_T)sizeof(soap->errnum); + if (!getsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_ERROR, (char*)&soap->errnum, &k) && !soap->errnum) /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */ + break; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); + soap->errnum = soap_socket_errno; + soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + else +#endif +#ifdef WITH_IPV6 + if (res->ai_next) + { res = res->ai_next; + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + goto again; + } + else +#endif + if (soap_socket_errno != SOAP_EINTR) + { soap->errnum = soap_socket_errno; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); + soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + } + else + break; + } +#ifdef WITH_IPV6 + soap->peerlen = 0; /* IPv6: already connected so use send() */ + freeaddrinfo(ressave); +#endif +#ifndef WITH_LEAN + if (soap->connect_timeout) +#if defined(WIN32) + { u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &blocking); + } +#elif defined(VXWORKS) + { u_long blocking = 0; + ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&blocking)); + } +#else + fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)&~O_NONBLOCK); +#endif +#endif + soap->socket = fd; + soap->imode &= ~SOAP_ENC_SSL; + soap->omode &= ~SOAP_ENC_SSL; + if (!strncmp(endpoint, "https:", 6)) + { +#ifdef WITH_OPENSSL + BIO *bio; + int r; + if (soap->proxy_host) + { short v; + unsigned int k = soap->omode; /* make sure we only parse HTTP */ + size_t n = soap->count; /* save the content length */ + char *userid, *passwd; + soap->omode &= ~SOAP_ENC; /* mask IO and ENC */ + soap->omode |= SOAP_IO_BUFFER; + soap_begin_send(soap); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connecting to proxy server\n")); + sprintf(soap->tmpbuf, "CONNECT %s:%d HTTP/%s", host, port, soap->http_version); + if ((soap->error = soap->fposthdr(soap, soap->tmpbuf, NULL))) + { soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } +#ifndef WITH_LEAN + if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761) + { sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd); + strcpy(soap->tmpbuf, "Basic "); + soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, strlen(soap->tmpbuf + 262)); + if ((soap->error = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf))) + { soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return soap->error; + } + } +#endif + if ((soap->error = soap->fposthdr(soap, NULL, NULL)) + || soap_flush(soap)) + { soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + soap->omode = k; + k = soap->imode; + soap->imode &= ~SOAP_ENC; /* mask IO and ENC */ + v = soap->version; /* preserve */ + userid = soap->userid; /* preserve */ + passwd = soap->passwd; /* preserve */ + if (soap_begin_recv(soap)) + { soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + soap->userid = userid; /* restore */ + soap->passwd = passwd; /* restore */ + soap->version = v; /* restore */ + soap->imode = k; /* restore */ + soap->count = n; /* restore */ + soap_begin_send(soap); + } + if (!soap->ctx && (soap->error = soap->fsslauth(soap))) + { soap_set_sender_error(soap, "SSL error", "SSL authentication failed in tcp_connect(): check password, key file, and ca file.", SOAP_SSL_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + soap->ssl = SSL_new(soap->ctx); + if (!soap->ssl) + { soap->fclosesocket(soap, (SOAP_SOCKET)fd); + soap->error = SOAP_SSL_ERROR; + return SOAP_INVALID_SOCKET; + } + if (soap->session) + { if (!strcmp(soap->session_host, host) && soap->session_port == port) + SSL_set_session(soap->ssl, soap->session); + SSL_SESSION_free(soap->session); + soap->session = NULL; + } + soap->imode |= SOAP_ENC_SSL; + soap->omode |= SOAP_ENC_SSL; + bio = BIO_new_socket((SOAP_SOCKET)fd, BIO_NOCLOSE); + SSL_set_bio(soap->ssl, bio, bio); +#ifndef WITH_LEAN + if (soap->connect_timeout) +#if defined(WIN32) + { u_long nonblocking = 1; + ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &nonblocking); + } +#elif defined(VXWORKS) + { u_long nonblocking = 1; + ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&nonblocking)); + } +#else + fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)|O_NONBLOCK); +#endif +#endif + for (;;) + { if ((r = SSL_connect(soap->ssl)) <= 0) + { int err = SSL_get_error(soap->ssl, r); + if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) + { soap_set_sender_error(soap, ssl_error(soap, r), "SSL connect failed in tcp_connect()", SOAP_SSL_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + if (soap->connect_timeout) + { struct timeval timeout; + fd_set fds; + if (soap->connect_timeout > 0) + { timeout.tv_sec = soap->connect_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->connect_timeout/1000000; + timeout.tv_usec = -soap->connect_timeout%1000000; + } + FD_ZERO(&fds); + FD_SET((SOAP_SOCKET)fd, &fds); + for (;;) + { int r = select((SOAP_SOCKET)(fd + 1), &fds, NULL, &fds, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n")); + soap_set_sender_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + } + continue; + } + } + break; + } +#ifndef WITH_LEAN + if (soap->connect_timeout) +#ifdef WIN32 + { u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &blocking); + } +#elif defined(VXWORKS) + { u_long blocking = 0; + ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&blocking)); + } +#else + fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)&~O_NONBLOCK); +#endif +#endif + if (soap->require_server_auth) + { X509 *peer; + int err; + if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK) + { soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL certificate presented by peer cannot be verified in tcp_connect()", SOAP_SSL_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + peer = SSL_get_peer_certificate(soap->ssl); + if (!peer) + { soap_set_sender_error(soap, "SSL error", "No SSL certificate was presented by the peer in tcp_connect()", SOAP_SSL_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + X509_NAME_get_text_by_NID(X509_get_subject_name(peer), NID_commonName, soap->msgbuf, sizeof(soap->msgbuf)); + X509_free(peer); + if (soap_tag_cmp(soap->msgbuf, host)) + { soap_set_sender_error(soap, "SSL error", "SSL certificate host name mismatch in tcp_connect()", SOAP_SSL_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + } +#else + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + soap->error = SOAP_SSL_ERROR; + return SOAP_INVALID_SOCKET; +#endif + } + return fd; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_bind(struct soap *soap, const char *host, int port, int backlog) +{ +#ifdef WITH_IPV6 + struct addrinfo *addrinfo = NULL; + struct addrinfo hints; + struct addrinfo res; + int err; +#endif +#ifndef WITH_LEAN + int len = SOAP_BUFLEN; + int set = 1; +#endif + if (soap_valid_socket(soap->master)) + { soap->fclosesocket(soap, (SOAP_SOCKET)soap->master); + soap->master = SOAP_INVALID_SOCKET; + } + soap->socket = SOAP_INVALID_SOCKET; + soap->errmode = 1; + if (tcp_init(soap)) + { soap_set_receiver_error(soap, tcp_error(soap), "TCP init failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#ifdef WITH_IPV6 + memset((void*)&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + hints.ai_socktype = SOCK_DGRAM; + else +#endif + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + soap->errmode = 2; + err = getaddrinfo(host, soap_int2s(soap, port), &hints, &addrinfo); + if (addrinfo) + { res = *addrinfo; + soap->peer = *((struct sockaddr_storage*)addrinfo->ai_addr); + soap->peerlen = addrinfo->ai_addrlen; + res.ai_addr = (struct sockaddr*)&soap->peer; + res.ai_addrlen = soap->peerlen; + freeaddrinfo(addrinfo); + } + if (err) + { soap_set_receiver_error(soap, gai_strerror(err), "getaddrinfo failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + soap->master = socket(res.ai_family, res.ai_socktype, res.ai_protocol); +#else +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + soap->master = (int)socket(AF_INET, SOCK_DGRAM, 0); + else +#endif + soap->master = (int)socket(AF_INET, SOCK_STREAM, 0); +#endif + soap->errmode = 0; + if (!soap_valid_socket(soap->master)) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "socket failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + soap->socket = soap->master; +#endif +#ifdef SOCKET_CLOSE_ON_EXEC +#ifdef WIN32 +#ifndef UNDER_CE + SetHandleInformation((HANDLE)soap->master, HANDLE_FLAG_INHERIT, 0); +#endif +#else + fcntl(soap->master, F_SETFD, 1); +#endif +#endif +#ifndef WITH_LEAN + if (soap->bind_flags && setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, soap->bind_flags, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + if (setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + if (setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#ifdef TCP_NODELAY + if (!(soap->omode & SOAP_IO_UDP) && setsockopt((SOAP_SOCKET)soap->master, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#endif +#endif +#ifdef WITH_IPV6 + soap->errmode = 0; + if (bind((SOAP_SOCKET)soap->master, res.ai_addr, res.ai_addrlen)) + { soap->errnum = soap_socket_errno; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n")); + soap_closesock(soap); + soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#else + soap->peerlen = sizeof(soap->peer); + memset((void*)&soap->peer, 0, sizeof(soap->peer)); + soap->peer.sin_family = AF_INET; + soap->errmode = 2; + if (host) + { if (soap->fresolve(soap, host, &soap->peer.sin_addr)) + { soap_set_receiver_error(soap, tcp_error(soap), "get host by name failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + } + else + soap->peer.sin_addr.s_addr = htonl(INADDR_ANY); + soap->peer.sin_port = htons((short)port); + soap->errmode = 0; + if (bind((SOAP_SOCKET)soap->master, (struct sockaddr*)&soap->peer, soap->peerlen)) + { soap->errnum = soap_socket_errno; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n")); + soap_closesock(soap); + soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#endif + if (!(soap->omode & SOAP_IO_UDP) && listen((SOAP_SOCKET)soap->master, backlog)) + { soap->errnum = soap_socket_errno; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n")); + soap_closesock(soap); + soap_set_receiver_error(soap, tcp_error(soap), "listen failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + return soap->master; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_poll(struct soap *soap) +{ +#ifndef WITH_LEAN + struct timeval timeout; + fd_set rfd, sfd, xfd; + int r; + timeout.tv_sec = 0; + timeout.tv_usec = 0; + FD_ZERO(&rfd); + FD_ZERO(&sfd); + FD_ZERO(&xfd); + if (soap_valid_socket(soap->socket)) + { FD_SET((SOAP_SOCKET)soap->socket, &rfd); + FD_SET((SOAP_SOCKET)soap->socket, &sfd); + FD_SET((SOAP_SOCKET)soap->socket, &xfd); + r = select((SOAP_SOCKET)(soap->socket + 1), &rfd, &sfd, &xfd, &timeout); + if (r > 0 && FD_ISSET((SOAP_SOCKET)soap->socket, &xfd)) + r = -1; + } + else if (soap_valid_socket(soap->master)) + { FD_SET((SOAP_SOCKET)soap->master, &sfd); + r = select((SOAP_SOCKET)(soap->master + 1), NULL, &sfd, NULL, &timeout); + } + else + return SOAP_OK; + if (r > 0) + { +#ifdef WITH_OPENSSL + if (soap->imode & SOAP_ENC_SSL) + { + if (soap_valid_socket(soap->socket) + && FD_ISSET((SOAP_SOCKET)soap->socket, &sfd) + && (!FD_ISSET((SOAP_SOCKET)soap->socket, &rfd) + || SSL_peek(soap->ssl, soap->tmpbuf, 1) > 0)) + return SOAP_OK; + } + else +#endif + if (soap_valid_socket(soap->socket) + && FD_ISSET((SOAP_SOCKET)soap->socket, &sfd) + && (!FD_ISSET((SOAP_SOCKET)soap->socket, &rfd) + || recv((SOAP_SOCKET)soap->socket, soap->tmpbuf, 1, MSG_PEEK) > 0)) + return SOAP_OK; + } + else if (r < 0) + { soap->errnum = soap_socket_errno; + if ((soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) && soap_socket_errno != SOAP_EINTR) + { soap_set_receiver_error(soap, tcp_error(soap), "select failed in soap_poll()", SOAP_TCP_ERROR); + return soap->error = SOAP_TCP_ERROR; + } + } + else + soap->errnum = 0; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Polling: other end down on socket=%d select=%d\n", soap->socket, r)); + return SOAP_EOF; +#else + return SOAP_OK; +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_accept(struct soap *soap, int s, struct sockaddr *a, int *n) +{ int fd; + fd = (int)accept((SOAP_SOCKET)s, a, (SOAP_SOCKLEN_T*)n); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */ +#ifdef SOCKET_CLOSE_ON_EXEC +#ifdef WIN32 +#ifndef UNDER_CE + SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0); +#endif +#else + fcntl(fd, F_SETFD, FD_CLOEXEC); +#endif +#endif + return fd; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_accept(struct soap *soap) +{ int n = (int)sizeof(soap->peer); +#ifndef WITH_LEAN + int len = SOAP_BUFLEN; + int set = 1; +#endif + soap->error = SOAP_OK; +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + return soap->socket = soap->master; +#endif + memset((void*)&soap->peer, 0, sizeof(soap->peer)); + soap->socket = SOAP_INVALID_SOCKET; + soap->errmode = 0; + soap->keep_alive = 0; + if (soap_valid_socket(soap->master)) + { for (;;) + { +#ifndef WITH_LEAN + if (soap->accept_timeout) + { struct timeval timeout; + fd_set fd; + if (soap->accept_timeout > 0) + { timeout.tv_sec = soap->accept_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->accept_timeout/1000000; + timeout.tv_usec = -soap->accept_timeout%1000000; + } + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->master, &fd); + for (;;) + { int r = select((SOAP_SOCKET)(soap->master + 1), &fd, &fd, NULL, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + soap_set_receiver_error(soap, "Timeout", "accept failed in soap_accept()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + if (soap_socket_errno != SOAP_EINTR) + { soap->errnum = soap_socket_errno; + soap_closesock(soap); + soap_set_sender_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + } +#if defined(WIN32) + { u_long nonblocking = 1; + ioctlsocket((SOAP_SOCKET)soap->master, FIONBIO, &nonblocking); + } +#elif defined(VXWORKS) + { u_long nonblocking = 1; + ioctl((SOAP_SOCKET)soap->master, FIONBIO, (int)(&nonblocking)); + } +#else + fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL)|O_NONBLOCK); +#endif + } + else +#if defined(WIN32) + { u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)soap->master, FIONBIO, &blocking); + } +#elif defined(VXWORKS) + { u_long blocking = 0; + ioctl((SOAP_SOCKET)soap->master, FIONBIO, (int)(&blocking)); + } +#else + fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL)&~O_NONBLOCK); +#endif +#endif + soap->socket = soap->faccept(soap, soap->master, (struct sockaddr*)&soap->peer, &n); + soap->peerlen = (size_t)n; + if (soap_valid_socket(soap->socket)) + { +#ifdef WITH_IPV6 +/* Use soap->host to store the numeric form of the remote host */ + getnameinfo((struct sockaddr*)&soap->peer, n, soap->host, sizeof(soap->host), NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket %d from %s\n", soap->socket, soap->host)); + soap->ip = 0; /* info stored in soap->peer and soap->host */ + soap->port = 0; /* info stored in soap->peer and soap->host */ +#else + soap->ip = ntohl(soap->peer.sin_addr.s_addr); + soap->port = (int)ntohs(soap->peer.sin_port); /* does not return port number on some systems */ + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket %d at port %d from IP %d.%d.%d.%d\n", soap->socket, soap->port, (int)(soap->ip>>24)&0xFF, (int)(soap->ip>>16)&0xFF, (int)(soap->ip>>8)&0xFF, (int)soap->ip&0xFF)); +#endif +#ifndef WITH_LEAN + if (soap->accept_flags & SO_LINGER) + { struct linger linger; + memset((void*)&linger, 0, sizeof(linger)); + linger.l_onoff = 1; + linger.l_linger = 0; + if (setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } + } + if ((soap->accept_flags & ~SO_LINGER) && setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, soap->accept_flags & ~SO_LINGER, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } + if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } + if (setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } + if (setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } +#ifdef TCP_NODELAY + if (!(soap->omode & SOAP_IO_UDP) && setsockopt((SOAP_SOCKET)soap->socket, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } +#endif +#endif + if (soap->accept_timeout) + { +#if defined(WIN32) + u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)soap->master, FIONBIO, &blocking); + ioctlsocket((SOAP_SOCKET)soap->socket, FIONBIO, &blocking); +#elif defined(VXWORKS) + u_long blocking = 0; + ioctl((SOAP_SOCKET)soap->master, FIONBIO, (int)(&blocking)); + ioctl((SOAP_SOCKET)soap->socket, FIONBIO, (int)(&blocking)); +#elif defined(PALM) + fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL,0)&~O_NONBLOCK); + fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL,0)&~O_NONBLOCK); +#elif defined(SYMBIAN) + long blocking = 0; + ioctl((SOAP_SOCKET)soap->master, 0/*FIONBIO*/, &blocking); +#else + fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL)&~O_NONBLOCK); + fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL)&~O_NONBLOCK); +#endif + } + soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0); + return soap->socket; + } + if (soap_socket_errno != SOAP_EINTR && soap_socket_errno != SOAP_EAGAIN) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept failed from %s\n", soap->host)); + soap->errnum = soap_socket_errno; + soap_set_receiver_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } + } + } + else + { soap->errnum = 0; + soap_set_receiver_error(soap, tcp_error(soap), "no master socket in soap_accept()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_disconnect(struct soap *soap) +{ +#ifdef WITH_OPENSSL + if (soap->ssl) + { int r, s = 0; + if (soap->session) + SSL_SESSION_free(soap->session); + if (*soap->host) + { soap->session = SSL_get1_session(soap->ssl); + if (soap->session) + { strcpy(soap->session_host, soap->host); + soap->session_port = soap->port; + } + } + r = SSL_shutdown(soap->ssl); + if (r != 1) + { s = ERR_get_error(); + if (s) + { if (soap_valid_socket(soap->socket)) + { soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 1); + soap->socket = SOAP_INVALID_SOCKET; + } + r = SSL_shutdown(soap->ssl); + } + } + DBGLOG(TEST, if (s) SOAP_MESSAGE(fdebug, "Shutdown failed: %d\n", SSL_get_error(soap->ssl, r))); + SSL_free(soap->ssl); + soap->ssl = NULL; + if (s) + return SOAP_SSL_ERROR; + ERR_remove_state(0); + } +#endif + if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP)) + { soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 2); + soap->fclosesocket(soap, (SOAP_SOCKET)soap->socket); + soap->socket = SOAP_INVALID_SOCKET; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_closesocket(struct soap *soap, SOAP_SOCKET fd) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Close socket %d\n", (int)fd)); + return closesocket(fd); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_shutdownsocket(struct soap *soap, SOAP_SOCKET fd, int how) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown socket %d how=%d\n", (int)fd, how)); + return shutdown(fd, how); +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_closesock(struct soap *soap) +{ register int status = soap->error; + if (status == SOAP_EOF || status == SOAP_TCP_ERROR || status == SOAP_SSL_ERROR || !soap->keep_alive) + { if (soap->fclose && (soap->error = soap->fclose(soap))) + return soap->error; + soap->keep_alive = 0; + } +#ifdef WITH_ZLIB + if (soap->zlib_state == SOAP_ZLIB_DEFLATE) + deflateEnd(&soap->d_stream); + else if (soap->zlib_state == SOAP_ZLIB_INFLATE) + inflateEnd(&soap->d_stream); + soap->zlib_state = SOAP_ZLIB_NONE; +#endif + return soap->error = status; +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_hash(register const char *s) +{ register size_t h = 0; + while (*s) + h = 65599*h + *s++; + return h % SOAP_IDHASH; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static void +soap_init_pht(struct soap *soap) +{ register int i; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing pointer hashtable\n")); + soap->pblk = NULL; + soap->pidx = 0; + for (i = 0; i < (int)SOAP_PTRHASH; i++) + soap->pht[i] = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_new1(soap_mode mode) +{ return soap_new2(mode, mode); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_new() +{ return soap_new2(SOAP_IO_DEFAULT, SOAP_IO_DEFAULT); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_new2(soap_mode imode, soap_mode omode) +{ struct soap *soap = (struct soap*)malloc(sizeof(struct soap)); + if (soap) + soap_init2(soap, imode, omode); + return soap; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_del(struct soap *soap) +{ free(soap); +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static void +soap_free_pht(struct soap *soap) +{ register struct soap_pblk *pb, *next; + register int i; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free pointer hashtable\n")); + for (pb = soap->pblk; pb; pb = next) + { next = pb->next; + SOAP_FREE(soap, pb); + } + soap->pblk = NULL; + soap->pidx = 0; + for (i = 0; i < (int)SOAP_PTRHASH; i++) + soap->pht[i] = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_embed(struct soap *soap, const void *p, const struct soap_array *a, int n, const char *tag, int type) +{ register int i; + struct soap_plist *pp; + if (soap->version != 1) + soap->encoding = 1; + if (a) + i = soap_array_pointer_lookup(soap, p, a, n, type, &pp); + else + i = soap_pointer_lookup(soap, p, type, &pp); + if (i) + { if (soap_is_embedded(soap, pp) + || soap_is_single(soap, pp)) + return 0; + soap_set_embedded(soap, pp); + } + return i; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_pointer_lookup(struct soap *soap, const void *p, int type, struct soap_plist **ppp) +{ register struct soap_plist *pp; + *ppp = NULL; + if (p) + { for (pp = soap->pht[soap_hash_ptr(p)]; pp; pp = pp->next) + { if (pp->ptr == p && pp->type == type) + { *ppp = pp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d id=%d\n", p, type, pp->id)); + return pp->id; + } + } + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d: not found\n", p, type)); + return 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_pointer_enter(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp) +{ register int h; + register struct soap_plist *pp; + if (!soap->pblk || soap->pidx >= SOAP_PTRBLK) + { register struct soap_pblk *pb = (struct soap_pblk*)SOAP_MALLOC(soap, sizeof(struct soap_pblk)); + if (!pb) + { soap->error = SOAP_EOM; + return 0; + } + pb->next = soap->pblk; + soap->pblk = pb; + soap->pidx = 0; + } + *ppp = pp = &soap->pblk->plist[soap->pidx++]; + if (a) + h = soap_hash_ptr(a->__ptr); + else + h = soap_hash_ptr(p); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pointer enter location=%p array=%p size=%d dim=%d type=%d id=%d\n", p, a?a->__ptr:NULL, a?a->__size:0, n, type, soap->idnum+1)); + pp->next = soap->pht[h]; + pp->type = type; + pp->mark1 = 0; + pp->mark2 = 0; + pp->ptr = p; + pp->array = a; + soap->pht[h] = pp; + pp->id = ++soap->idnum; + return pp->id; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_array_pointer_lookup(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp) +{ register struct soap_plist *pp; + *ppp = NULL; + if (!p || !a->__ptr) + return 0; + for (pp = soap->pht[soap_hash_ptr(a->__ptr)]; pp; pp = pp->next) + { if (pp->type == type && pp->array && pp->array->__ptr == a->__ptr) + { register int i; + for (i = 0; i < n; i++) + if (((const int*)&pp->array->__size)[i] != ((const int*)&a->__size)[i]) + break; + if (i == n) + { *ppp = pp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d id=%d\n", a->__ptr, type, pp->id)); + return pp->id; + } + } + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d: not found\n", a->__ptr, type)); + return 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_begin_count(struct soap *soap) +{ soap_clr_attr(soap); + soap_set_local_namespaces(soap); +#ifndef WITH_LEANER + if ((soap->mode & SOAP_ENC_DIME) || (soap->omode & SOAP_ENC_DIME)) + soap->mode = soap->omode | SOAP_IO_LENGTH | SOAP_ENC_DIME; + else +#endif + { soap->mode = soap->omode; + if ((soap->mode & SOAP_IO) == SOAP_IO_STORE + || (((soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_ENC_XML)) +#ifndef WITH_LEANER + && !soap->fpreparesend +#endif + )) + soap->mode &= ~SOAP_IO_LENGTH; + else + soap->mode |= SOAP_IO_LENGTH; + } +#ifdef WITH_ZLIB + if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH) + { if (!(soap->mode & SOAP_ENC_DIME)) + soap->mode &= ~SOAP_IO_LENGTH; + if (soap->mode & SOAP_ENC_XML) + soap->mode |= SOAP_IO_BUFFER; + else + soap->mode |= SOAP_IO_STORE; + } +#endif + if (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH)) + soap->mode |= SOAP_XML_TREE; +#ifndef WITH_LEANER + if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME)) + soap->mode |= SOAP_ENC_MIME; + else + soap->mode &= ~SOAP_ENC_MTOM; + if (soap->mode & SOAP_ENC_MIME) + soap_select_mime_boundary(soap); + soap->dime.list = soap->dime.last; /* keep track of last DIME attachment */ +#endif + soap->count = 0; + soap->ns = 0; + soap->null = 0; + soap->position = 0; + soap->mustUnderstand = 0; + soap->encoding = 0; + soap->part = SOAP_BEGIN; + soap->idnum = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin count phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count)); +#ifndef WITH_LEANER + soap->dime.count = 0; /* count # of attachments */ + soap->dime.size = 0; /* accumulate total size of attachments */ + if (soap->fprepareinit && (soap->mode & SOAP_IO) != SOAP_IO_STORE) + return soap->error = soap->fprepareinit(soap); +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_end_count(struct soap *soap) +{ +#ifndef WITH_LEANER + if (soap->fpreparefinal) + return soap->error = soap->fpreparefinal(soap); +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of count phase\n")); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_begin_send(struct soap *soap) +{ soap->error = SOAP_OK; + soap_clr_attr(soap); + soap_set_local_namespaces(soap); + soap->mode = soap->omode | (soap->mode & (SOAP_IO_LENGTH | SOAP_ENC_DIME)); +#ifdef WITH_ZLIB + if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH) + { if (soap->mode & SOAP_ENC_XML) + soap->mode |= SOAP_IO_BUFFER; + else + soap->mode |= SOAP_IO_STORE; + } +#endif +#ifdef WITH_UDP + if ((soap->mode & SOAP_IO_UDP)) + { soap->mode |= SOAP_ENC_XML; + if (soap->count > SOAP_BUFLEN) + return soap->error = SOAP_UDP_ERROR; + } +#endif + if ((soap->mode & SOAP_IO) == SOAP_IO_FLUSH && soap_valid_socket(soap->socket)) + { if (soap->count || (soap->mode & SOAP_IO_LENGTH) || (soap->mode & SOAP_ENC_XML)) + soap->mode |= SOAP_IO_BUFFER; + else + soap->mode |= SOAP_IO_STORE; + } + soap->mode &= ~SOAP_IO_LENGTH; + if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) + soap_new_block(soap); + if (!(soap->mode & SOAP_IO_KEEPALIVE)) + soap->keep_alive = 0; + if (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH)) + soap->mode |= SOAP_XML_TREE; +#ifndef WITH_LEANER + if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME)) + { soap->mode |= SOAP_ENC_MIME; + soap->mode &= ~SOAP_ENC_DIME; + } + else + soap->mode &= ~SOAP_ENC_MTOM; + if (soap->mode & SOAP_ENC_MIME) + soap_select_mime_boundary(soap); +#ifdef WIN32 +#ifndef UNDER_CE +#ifndef WITH_FASTCGI + if (!soap_valid_socket(soap->socket)) /* Set win32 stdout or soap->sendfd to BINARY, e.g. to support DIME */ +#ifdef __BORLANDC__ + setmode((SOAP_SOCKET)soap->sendfd, O_BINARY); +#else + _setmode((SOAP_SOCKET)soap->sendfd, _O_BINARY); +#endif +#endif +#endif +#endif +#endif + if (soap->mode & SOAP_IO) + { soap->bufidx = 0; + soap->buflen = 0; + } + soap->chunksize = 0; + soap->ns = 0; + soap->null = 0; + soap->position = 0; + soap->mustUnderstand = 0; + soap->encoding = 0; + soap->idnum = 0; + soap->level = 0; +#ifdef WITH_ZLIB + soap->z_ratio_out = 1.0; + if ((soap->mode & SOAP_ENC_ZLIB) && soap->zlib_state != SOAP_ZLIB_DEFLATE) + { +#ifdef WITH_GZIP + memcpy(soap->z_buf, "\37\213\10\0\0\0\0\0\0\377", 10); + soap->d_stream.next_out = (Byte*)soap->z_buf + 10; + soap->d_stream.avail_out = SOAP_BUFLEN - 10; + soap->z_crc = crc32(0L, NULL, 0); + if (deflateInit2(&soap->d_stream, soap->z_level, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY) != Z_OK) +#else + soap->d_stream.next_out = (Byte*)soap->z_buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + if (deflateInit(&soap->d_stream, soap->z_level) != Z_OK) +#endif + return soap->error = SOAP_ZLIB_ERROR; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflate initialized\n")); + soap->zlib_state = SOAP_ZLIB_DEFLATE; + } +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin send phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count)); + soap->part = SOAP_BEGIN; +#ifndef WITH_LEANER + if (soap->fprepareinit && (soap->mode & SOAP_IO) == SOAP_IO_STORE) + soap->fprepareinit(soap); +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_embedded(struct soap *soap, const void *p, int t) +{ struct soap_plist *pp; + if (soap_pointer_lookup(soap, p, t, &pp)) + { pp->mark1 = 1; + pp->mark2 = 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded %p type=%d mark set to 1\n", p, t)); + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_reference(struct soap *soap, const void *p, int t) +{ struct soap_plist *pp; + if (!p || (soap->mode & SOAP_XML_TREE)) + return 1; + if (soap_pointer_lookup(soap, p, t, &pp)) + { if (pp->mark1 == 0) + { pp->mark1 = 2; + pp->mark2 = 2; + } + } + else if (soap_pointer_enter(soap, p, NULL, 0, t, &pp)) + { pp->mark1 = 0; + pp->mark2 = 0; + } + else + return 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reference %p type=%d (%d %d)\n", p, t, (int)pp->mark1, (int)pp->mark2)); + return pp->mark1; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_array_reference(struct soap *soap, const void *p, const struct soap_array *a, int n, int t) +{ register int i; + struct soap_plist *pp; + if (!p || !a->__ptr) + return 1; + i = soap_array_pointer_lookup(soap, p, a, n, t, &pp); + if (i) + { if (pp->mark1 == 0) + { pp->mark1 = 2; + pp->mark2 = 2; + } + } + else if (!soap_pointer_enter(soap, p, a, n, t, &pp)) + return 1; + else + { pp->mark1 = 0; + pp->mark2 = 0; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array reference %p ptr=%p dim=%d type=%d (%d %d)\n", p, a->__ptr, n, t, (int)pp->mark1, (int)pp->mark2)); + return pp->mark1; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_embedded_id(struct soap *soap, int id, const void *p, int t) +{ struct soap_plist *pp; + if (soap->mode & SOAP_XML_TREE) + return id; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id %p type=%d id=%d\n", p, t, id)); + if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER) + { if (id < 0) + { id = soap_pointer_lookup(soap, p, t, &pp); + if (id) + { if (soap->mode & SOAP_IO_LENGTH) + pp->mark1 = 2; + else + pp->mark2 = 2; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id multiref id=%d %p type=%d = (%d %d)\n", id, p, t, (int)pp->mark1, (int)pp->mark2)); + } + return -1; + } + return id; + } + if (id < 0) + id = soap_pointer_lookup(soap, p, t, &pp); + else if (id && !soap_pointer_lookup(soap, p, t, &pp)) + return 0; + if (id && pp) + { if (soap->mode & SOAP_IO_LENGTH) + pp->mark1 = 1; + else + pp->mark2 = 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id embedded ref id=%d %p type=%d = (%d %d)\n", id, p, t, (int)pp->mark1, (int)pp->mark2)); + } + return id; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_is_embedded(struct soap *soap, struct soap_plist *pp) +{ if (!pp) + return 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Is embedded? %d %d\n", (int)pp->mark1, (int)pp->mark2)); + if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER) + { if (soap->mode & SOAP_IO_LENGTH) + return pp->mark1 != 0; + return pp->mark2 != 0; + } + if (soap->mode & SOAP_IO_LENGTH) + return pp->mark1 == 1; + return pp->mark2 == 1; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_is_single(struct soap *soap, struct soap_plist *pp) +{ if (soap->part == SOAP_IN_HEADER) + return 1; + if (!pp) + return 0; + if (soap->mode & SOAP_IO_LENGTH) + return pp->mark1 == 0; + return pp->mark2 == 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_embedded(struct soap *soap, struct soap_plist *pp) +{ if (!pp) + return; + if (soap->mode & SOAP_IO_LENGTH) + pp->mark1 = 1; + else + pp->mark2 = 1; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_attachment(struct soap *soap, const char *tag, int id, const void *p, const struct soap_array *a, const char *aid, const char *atype, const char *aoptions, int n, const char *type, int t) +{ struct soap_plist *pp; + int i; + if (!p || !a->__ptr || (!aid && !atype)) + return soap_element_id(soap, tag, id, p, a, n, type, t); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attachment tag='%s' id='%s' (%d) type='%s'\n", tag, aid?aid:"", id, atype?atype:"")); + i = soap_array_pointer_lookup(soap, p, a, n, t, &pp); + if (!i) + { i = soap_pointer_enter(soap, p, a, n, t, &pp); + if (!i) + { soap->error = SOAP_EOM; + return -1; + } + } + if (id <= 0) + id = i; + if (!aid) + { sprintf(soap->tmpbuf, soap->dime_id_format, id); + aid = soap_strdup(soap, soap->tmpbuf); + } + /* Add MTOM xop:Include element when necessary */ + /* TODO: this code to be obsoleted with new import/xop.h conventions */ + if ((soap->mode & SOAP_ENC_MTOM) && strcmp(tag, "xop:Include")) + { if (soap_element_begin_out(soap, tag, 0, type) + || soap_element_href(soap, "xop:Include", 0, "href", aid) + || soap_element_end_out(soap, tag)) + return soap->error; + } + else if (soap_element_href(soap, tag, 0, "href", aid)) + return soap->error; + if (soap->mode & SOAP_IO_LENGTH) + { if (pp->mark1 != 3) + { struct soap_multipart *content; + if (soap->mode & SOAP_ENC_MTOM) + content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, (char*)a->__ptr, a->__size); + else + content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, (char*)a->__ptr, a->__size); + if (!content) + { soap->error = SOAP_EOM; + return -1; + } + if (!strncmp(aid, "cid:", 4)) /* RFC 2111 */ + { if (soap->mode & SOAP_ENC_MTOM) + { char *s = (char*)soap_malloc(soap, strlen(aid) - 1); + if (s) + { *s = '<'; + strcpy(s + 1, aid + 4); + strcat(s, ">"); + content->id = s; + } + } + else + content->id = aid + 4; + } + else + content->id = aid; + content->type = atype; + content->options = aoptions; + content->encoding = SOAP_MIME_BINARY; + pp->mark1 = 3; + } + } + else + pp->mark2 = 3; + return -1; +} +#endif +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static void +soap_init_iht(struct soap *soap) +{ register int i; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing ID hashtable\n")); + for (i = 0; i < SOAP_IDHASH; i++) + soap->iht[i] = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static void +soap_free_iht(struct soap *soap) +{ register int i; + register struct soap_ilist *ip, *p; + register struct soap_flist *fp, *fq; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free ID hashtable\n")); + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = p) + { for (fp = ip->flist; fp; fp = fq) + { fq = fp->next; + SOAP_FREE(soap, fp); + } + p = ip->next; + SOAP_FREE(soap, ip); + } + soap->iht[i] = NULL; + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +struct soap_ilist * +SOAP_FMAC2 +soap_lookup(struct soap *soap, const char *id) +{ register struct soap_ilist *ip; + for (ip = soap->iht[soap_hash(id)]; ip; ip = ip->next) + if (!strcmp(ip->id, id)) + return ip; + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +struct soap_ilist * +SOAP_FMAC2 +soap_enter(struct soap *soap, const char *id) +{ register size_t h; + register struct soap_ilist *ip; + ip = (struct soap_ilist*)SOAP_MALLOC(soap, sizeof(struct soap_ilist) + strlen(id)); + if (ip) + { h = soap_hash(id); + strcpy(ip->id, id); + ip->next = soap->iht[h]; + soap->iht[h] = ip; + return ip; + } + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_malloc(struct soap *soap, size_t n) +{ register char *p; + if (!n) + return (void*)SOAP_NON_NULL; + if (!soap) + return SOAP_MALLOC(soap, n); + n += (-(long)n) & (sizeof(void*)-1); /* align at 4-, 8- or 16-byte boundary */ + if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(void*) + sizeof(size_t)))) + { soap->error = SOAP_EOM; + return NULL; + } + /* keep chain of alloced cells for later destruction */ + soap->alloced = 1; + *(void**)(p + n) = soap->alist; + *(size_t*)(p + n + sizeof(void*)) = n; + soap->alist = p + n; + return p; +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +static void +soap_init_mht(struct soap *soap) +{ register int i; + for (i = 0; i < (int)SOAP_PTRHASH; i++) + soap->mht[i] = NULL; +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +static void +soap_free_mht(struct soap *soap) +{ register int i; + register struct soap_mlist *mp, *mq; + for (i = 0; i < (int)SOAP_PTRHASH; i++) + { for (mp = soap->mht[i]; mp; mp = mq) + { mq = mp->next; + if (mp->live) + fprintf(stderr, "%s(%d): malloc() = %p not freed (memory leak or forgot to call soap_end()?)\n", mp->file, mp->line, mp->ptr); + free(mp); + } + soap->mht[i] = NULL; + } +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_track_malloc(struct soap *soap, const char *file, int line, size_t size) +{ register void *p = malloc(size); + if (soap) + { register int h = soap_hash_ptr(p); + register struct soap_mlist *mp = (struct soap_mlist*)malloc(sizeof(struct soap_mlist)); + if (soap->fdebug[SOAP_INDEX_TEST]) + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): malloc(%lu) = %p\n", file, line, (unsigned long)size, p)); + mp->next = soap->mht[h]; + mp->ptr = p; + mp->file = file; + mp->line = line; + mp->live = 1; + soap->mht[h] = mp; + } + return p; +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_track_free(struct soap *soap, const char *file, int line, void *p) +{ register int h = soap_hash_ptr(p); + register struct soap_mlist *mp; + for (mp = soap->mht[h]; mp; mp = mp->next) + if (mp->ptr == p) + break; + if (mp) + { if (mp->live) + { free(p); + if (soap->fdebug[SOAP_INDEX_TEST]) + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): free(%p)\n", file, line, p)); + mp->live = 0; + } + else + fprintf(stderr, "%s(%d): free(%p) double free of pointer malloced at %s(%d)\n", file, line, p, mp->file, mp->line); + } + else + fprintf(stderr, "%s(%d): free(%p) pointer not malloced\n", file, line, p); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +static void +soap_track_unlink(struct soap *soap, const void *p) +{ register int h = soap_hash_ptr(p); + register struct soap_mlist *mp; + for (mp = soap->mht[h]; mp; mp = mp->next) + if (mp->ptr == p) + break; + if (mp) + mp->live = 0; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_dealloc(struct soap *soap, void *p) +{ if (!soap) + return; + if (p) + { register char **q; + for (q = (char**)&soap->alist; *q; q = *(char***)q) + { if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*)))) + { *q = **(char***)q; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Freed data at %p\n", p)); + SOAP_FREE(soap, p); + return; + } + } + soap_delete(soap, p); + } + else + { register char *q; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free all soap_malloc() data\n")); + while (soap->alist) + { q = (char*)soap->alist; + soap->alist = *(void**)q; + q -= *(size_t*)(q + sizeof(void*)); + SOAP_FREE(soap, q); + } + } + /* we must assume these were deallocated: */ + soap->action = NULL; + soap->fault = NULL; + soap->header = NULL; + soap->userid = NULL; + soap->passwd = NULL; + soap->authrealm = NULL; +#ifndef WITH_LEANER + soap_clr_mime(soap); +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_delete(struct soap *soap, void *p) +{ register struct soap_clist **cp = &soap->clist; + if (p) + { while (*cp) + { if (p == (*cp)->ptr) + { register struct soap_clist *q = *cp; + *cp = q->next; + q->fdelete(q); + SOAP_FREE(soap, q); + return; + } + cp = &(*cp)->next; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: address not in list\n", p)); + } + else + { while (*cp) + { register struct soap_clist *q = *cp; + *cp = q->next; + if (q->ptr == (void*)soap->fault) + soap->fault = NULL; /* this was deallocated */ + else if (q->ptr == (void*)soap->header) + soap->header = NULL; /* this was deallocated */ + q->fdelete(q); + SOAP_FREE(soap, q); + } + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +struct soap_clist * +SOAP_FMAC2 +soap_link(struct soap *soap, void *p, int t, int n, void (*fdelete)(struct soap_clist*)) +{ register struct soap_clist *cp; + if ((cp = (struct soap_clist*)SOAP_MALLOC(soap, sizeof(struct soap_clist)))) + { cp->next = soap->clist; + cp->type = t; + cp->size = n; + cp->ptr = p; + cp->fdelete = fdelete; + soap->clist = cp; + } + return cp; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_unlink(struct soap *soap, const void *p) +{ register char **q; + register struct soap_clist **cp; + if (!soap || !p) + return; + for (q = (char**)&soap->alist; *q; q = *(char***)q) + { if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*)))) + { *q = **(char***)q; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked data %p\n", p)); +#ifdef SOAP_DEBUG + soap_track_unlink(soap, p); +#endif + return; + } + } + for (cp = &soap->clist; *cp; cp = &(*cp)->next) + { if (p == (*cp)->ptr) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked class instance %p\n", p)); + q = (char**)*cp; + *cp = (*cp)->next; + SOAP_FREE(soap, q); + return; + } + } +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_lookup_type(struct soap *soap, const char *id) +{ register struct soap_ilist *ip; + if (id && *id) + { ip = soap_lookup(soap, id); + if (ip) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup id='%s' type=%d\n", id, ip->type)); + return ip->type; + } + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "lookup type id='%s' NOT FOUND! Need to get it from xsi:type\n", id)); + return 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_id_lookup(struct soap *soap, const char *id, void **p, int t, size_t n, unsigned int k) +{ struct soap_ilist *ip; + void **q; + if (!p || !id || !*id) + return p; + ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */ + if (!ip) + { ip = soap_enter(soap, id); /* new hash table entry for string id */ + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding first href='%s' type=%d %p (%u bytes)\n", id, t, p, (unsigned int)n)); + ip->type = t; + ip->size = n; + ip->link = p; + ip->copy = NULL; + ip->flist = NULL; + ip->ptr = NULL; + ip->level = k; + *p = NULL; + } + else if (ip->ptr) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolved href='%s' type=%d location=%p (%u bytes)\n", id, t, ip->ptr, (unsigned int)n)); + if (ip->type != t) + { strcpy(soap->id, id); + soap->error = SOAP_HREF; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility: id type=%d href type=%d\n", ip->type, t)); + return NULL; + } + while (ip->level < k) + { q = (void**)soap_malloc(soap, sizeof(void*)); + if (!q) + return NULL; + *p = (void*)q; + p = q; + k--; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); + } + *p = ip->ptr; + } + else if (ip->level > k) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving level %u pointers to href='%s'\n", ip->level, id)); + while (ip->level > k) + { void *s, **r = &ip->link; + q = (void**)ip->link; + while (q) + { *r = (void*)soap_malloc(soap, sizeof(void*)); + s = *q; + *q = *r; + r = (void**)*r; + q = (void**)s; + } + *r = NULL; + ip->size = n; + ip->copy = NULL; + ip->level = ip->level - 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); + } + q = (void**)ip->link; + ip->link = p; + *p = (void*)q; + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarded href='%s' type=%d location=%p (%u bytes)\n", id, t, p, (unsigned int)n)); + while (ip->level < k) + { q = (void**)soap_malloc(soap, sizeof(void*)); + *p = q; + p = q; + k--; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); + } + q = (void**)ip->link; + ip->link = p; + *p = (void*)q; + } + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_id_forward(struct soap *soap, const char *href, void *p, int st, int tt, size_t n, unsigned int k, void (*fcopy)(struct soap*, int, int, void*, const void*, size_t)) +{ struct soap_ilist *ip; + if (!p || !href || !*href) + return p; + ip = soap_lookup(soap, href); /* lookup pointer to hash table entry for string id */ + if (!ip) + { ip = soap_enter(soap, href); /* new hash table entry for string id */ + ip->type = st; + ip->size = n; + ip->link = NULL; + ip->copy = NULL; + ip->ptr = NULL; + ip->level = 0; + ip->flist = NULL; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "New entry href='%s' type=%d size=%lu level=%d location=%p\n", href, st, (unsigned long)n, k, p)); + } + else if (ip->type != st || (ip->level == k && ip->size != n)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n", href, ip->type, (unsigned long)ip->size, k, st, (unsigned long)n)); + strcpy(soap->id, href); + soap->error = SOAP_HREF; + return NULL; + } + if (fcopy || n < sizeof(void*) || *href != '#') + { register struct soap_flist *fp = (struct soap_flist*)SOAP_MALLOC(soap, sizeof(struct soap_flist)); + if (!fp) + { soap->error = SOAP_EOM; + return NULL; + } + fp->next = ip->flist; + fp->type = tt; + fp->ptr = p; + fp->level = k; + if (fcopy) + fp->fcopy = fcopy; + else + fp->fcopy = soap_fcopy; + ip->flist = fp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding type=%d (target type=%d) size=%lu location=%p level=%u href='%s'\n", st, tt, (unsigned long)n, p, k, href)); + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding copying address %p for type=%d href='%s'\n", p, st, href)); + *(void**)p = ip->copy; + ip->copy = p; + } + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_id_enter(struct soap *soap, const char *id, void *p, int t, size_t n, unsigned int k, const char *type, const char *arrayType, void *(*finstantiate)(struct soap*, int, const char*, const char*, size_t*)) +{ +#ifndef WITH_NOIDREF + struct soap_ilist *ip; +#endif + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Enter id='%s' type=%d loc=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k)); + soap->alloced = 0; + if (!p) + { if (finstantiate) + p = finstantiate(soap, t, type, arrayType, &n); + else + p = soap_malloc(soap, n); + if (p) + soap->alloced = 1; + } +#ifndef WITH_NOIDREF + if (!id || !*id) +#endif + return p; +#ifndef WITH_NOIDREF + ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */ + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Lookup entry id='%s for location=%p'\n", id, p)); + if (!ip) + { ip = soap_enter(soap, id); /* new hash table entry for string id */ + ip->type = t; + ip->link = NULL; + ip->copy = NULL; + ip->flist = NULL; + ip->size = n; + ip->ptr = p; + ip->level = k; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "New entry id='%s' type=%d size=%lu level=%u location=%p\n", id, t, (unsigned long)n, k, p)); + } + else if ((ip->type != t || (ip->level == k && ip->size != n)) && (ip->copy || ip->flist)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n", id, ip->type, (unsigned long)ip->size, k, t, (unsigned long)n)); + strcpy(soap->id, id); + soap->error = SOAP_HREF; + return NULL; + } + else if (ip->ptr) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Multiply defined id='%s'\n", id)); + strcpy(soap->id, id); + soap->error = SOAP_DUPLICATE_ID; + return NULL; + } + else + { ip->size = n; + ip->ptr = p; + ip->level = k; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update entry id='%s' type=%d location=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k)); + } + return ip->ptr; +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_fcopy(struct soap *soap, int st, int tt, void *p, const void *q, size_t n) +{ DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Copying data type=%d (target type=%d) %p -> %p (%lu bytes)\n", st, tt, q, p, (unsigned long)n)); + memcpy(p, q, n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_end_send(struct soap *soap) +{ +#ifndef WITH_LEANER + if (soap->dime.list) + { /* SOAP body referenced attachments must appear first */ + soap->dime.last->next = soap->dime.first; + soap->dime.first = soap->dime.list->next; + soap->dime.list->next = NULL; + soap->dime.last = soap->dime.list; + } + if (soap_putdime(soap) || soap_putmime(soap)) + return soap->error; + soap->mime.list = NULL; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->dime.list = NULL; + soap->dime.first = NULL; + soap->dime.last = NULL; +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End send\n")); + if (soap->mode & SOAP_IO) /* need to flush the remaining data in buffer */ + { if (soap_flush(soap)) +#ifdef WITH_ZLIB + { if (soap->mode & SOAP_ENC_ZLIB && soap->zlib_state == SOAP_ZLIB_DEFLATE) + { soap->zlib_state = SOAP_ZLIB_NONE; + deflateEnd(&soap->d_stream); + } + return soap->error; + } +#else + return soap->error; +#endif +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { int r; + soap->d_stream.avail_in = 0; + do + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating remainder\n")); + r = deflate(&soap->d_stream, Z_FINISH); + if (soap->d_stream.avail_out != SOAP_BUFLEN) + { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN - soap->d_stream.avail_out)) + { soap->zlib_state = SOAP_ZLIB_NONE; + deflateEnd(&soap->d_stream); + return soap->error; + } + soap->d_stream.next_out = (Byte*)soap->z_buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + } + } while (r == Z_OK); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out)); + soap->z_ratio_out = (float)soap->d_stream.total_out / (float)soap->d_stream.total_in; + soap->mode &= ~SOAP_ENC_ZLIB; + soap->zlib_state = SOAP_ZLIB_NONE; + if (deflateEnd(&soap->d_stream) != Z_OK || r != Z_STREAM_END) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to end deflate: %s\n", soap->d_stream.msg?soap->d_stream.msg:"")); + return soap->error = SOAP_ZLIB_ERROR; + } +#ifdef WITH_GZIP + soap->z_buf[0] = soap->z_crc & 0xFF; + soap->z_buf[1] = (soap->z_crc >> 8) & 0xFF; + soap->z_buf[2] = (soap->z_crc >> 16) & 0xFF; + soap->z_buf[3] = (soap->z_crc >> 24) & 0xFF; + soap->z_buf[4] = soap->d_stream.total_in & 0xFF; + soap->z_buf[5] = (soap->d_stream.total_in >> 8) & 0xFF; + soap->z_buf[6] = (soap->d_stream.total_in >> 16) & 0xFF; + soap->z_buf[7] = (soap->d_stream.total_in >> 24) & 0xFF; + if (soap_flush_raw(soap, soap->z_buf, 8)) + return soap->error; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip crc32=%lu\n", (unsigned long)soap->z_crc)); +#endif + } +#endif + if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) + { char *p; +#ifndef WITH_NOHTTP + if (!(soap->mode & SOAP_ENC_XML)) + { soap->mode--; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending buffered message of length %u\n", (unsigned int)soap->blist->size)); + if (soap->status >= SOAP_POST) + soap->error = soap->fpost(soap, soap->endpoint, soap->host, soap->port, soap->path, soap->action, soap->blist->size); + else if (soap->status != SOAP_STOP) + soap->error = soap->fresponse(soap, soap->status, soap->blist->size); + if (soap->error || soap_flush(soap)) + return soap->error; + soap->mode++; + } +#endif + for (p = soap_first_block(soap); p; p = soap_next_block(soap)) + { DBGMSG(SENT, p, soap_block_size(soap)); + if ((soap->error = soap->fsend(soap, p, soap_block_size(soap)))) + { soap_end_block(soap); + return soap->error; + } + } + soap_end_block(soap); + } +#ifndef WITH_LEANER + else if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) + { DBGMSG(SENT, "\r\n0\r\n\r\n", 7); + if ((soap->error = soap->fsend(soap, "\r\n0\r\n\r\n", 7))) + return soap->error; + } +#endif + } +#ifdef WITH_TCPFIN +#ifdef WITH_OPENSSL + if (!soap->ssl && soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP)) + soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 1); /* Send TCP FIN */ +#else + if (soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP)) + soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 1); /* Send TCP FIN */ +#endif +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of send phase\n")); + soap->omode &= ~SOAP_XML_SEC; + soap->count = 0; + soap->part = SOAP_END; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_end_recv(struct soap *soap) +{ soap->part = SOAP_END; +#ifndef WITH_LEANER + if ((soap->mode & SOAP_ENC_DIME) && soap_getdime(soap)) + return soap->error; + soap->dime.list = soap->dime.first; + soap->dime.first = NULL; + soap->dime.last = NULL; + if ((soap->mode & SOAP_ENC_MIME) && soap_getmime(soap)) + return soap->error; + soap->mime.list = soap->mime.first; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = NULL; +#endif + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "End of receive message ok\n")); +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { soap->mode &= ~SOAP_ENC_ZLIB; + memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN); + soap->bufidx = (char*)soap->d_stream.next_in - soap->z_buf; + soap->buflen = soap->z_buflen; + soap->zlib_state = SOAP_ZLIB_NONE; + if (inflateEnd(&soap->d_stream) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; +#ifdef WITH_GZIP + if (soap->zlib_in == SOAP_ZLIB_GZIP) + { soap_wchar c; + short i; + for (i = 0; i < 8; i++) + { if ((int)(c = soap_getchar(soap)) == EOF) + return soap->error = SOAP_EOF; + soap->z_buf[i] = (char)c; + } + if (soap->z_crc != ((uLong)(unsigned char)soap->z_buf[0] | ((uLong)(unsigned char)soap->z_buf[1] << 8) | ((uLong)(unsigned char)soap->z_buf[2] << 16) | ((uLong)(unsigned char)soap->z_buf[3] << 24))) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: crc check failed, message corrupted? (crc32=%lu)\n", (unsigned long)soap->z_crc)); + return soap->error = SOAP_ZLIB_ERROR; + } + if (soap->d_stream.total_out != ((uLong)(unsigned char)soap->z_buf[4] | ((uLong)(unsigned char)soap->z_buf[5] << 8) | ((uLong)(unsigned char)soap->z_buf[6] << 16) | ((uLong)(unsigned char)soap->z_buf[7] << 24))) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: incorrect message length\n")); + return soap->error = SOAP_ZLIB_ERROR; + } + } +#endif + } +#endif + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) + while ((int)soap_getchar(soap) != EOF) /* advance to last chunk */ + ; + if (soap->fdisconnect && (soap->error = soap->fdisconnect(soap))) + return soap->error; +#ifndef WITH_NOIDREF + return soap_resolve(soap); +#else +#ifndef WITH_LEANER + if (soap->xlist) + { if (soap->mode & SOAP_ENC_MTOM) + return soap->error = SOAP_MIME_HREF; + return soap->error = SOAP_DIME_HREF; + } +#endif + return SOAP_OK; +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_free(struct soap *soap) +{ register struct Namespace *ns; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free namespace stack\n")); + while (soap->nlist) + { register struct soap_nlist *np = soap->nlist->next; + SOAP_FREE(soap, soap->nlist); + soap->nlist = np; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free any remaining temp blocks\n")); + while (soap->blist) + soap_end_block(soap); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute storage\n")); + while (soap->attributes) + { register struct soap_attribute *tp = soap->attributes->next; + if (soap->attributes->value) + SOAP_FREE(soap, soap->attributes->value); + SOAP_FREE(soap, soap->attributes); + soap->attributes = tp; + } +#ifdef WITH_FAST + if (soap->labbuf) + SOAP_FREE(soap, soap->labbuf); + soap->labbuf = NULL; + soap->lablen = 0; + soap->labidx = 0; +#endif + ns = soap->local_namespaces; + if (ns) + { for (; ns->id; ns++) + { if (ns->out) + { if (soap->encodingStyle == ns->out) + soap->encodingStyle = SOAP_STR_EOS; + SOAP_FREE(soap, ns->out); + ns->out = NULL; + } + if (soap->encodingStyle == ns->ns) + soap->encodingStyle = SOAP_STR_EOS; + } + SOAP_FREE(soap, soap->local_namespaces); + soap->local_namespaces = NULL; + } +#ifndef WITH_LEANER + while (soap->xlist) + { struct soap_xlist *xp = soap->xlist->next; + SOAP_FREE(soap, soap->xlist); + soap->xlist = xp; + } +#endif +#ifndef WITH_NOIDREF + soap_free_pht(soap); + soap_free_iht(soap); +#endif +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +static void +soap_init_logs(struct soap *soap) +{ int i; + for (i = 0; i < SOAP_MAXLOGS; i++) + { soap->logfile[i] = NULL; + soap->fdebug[i] = NULL; + } +} +#endif + +/******************************************************************************/ +#if !defined(WITH_LEAN) || defined(SOAP_DEBUG) +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_open_logfile(struct soap *soap, int i) +{ if (soap->logfile[i]) + soap->fdebug[i] = fopen(soap->logfile[i], i < 2 ? "ab" : "a"); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +static void +soap_close_logfile(struct soap *soap, int i) +{ if (soap->fdebug[i]) + { fclose(soap->fdebug[i]); + soap->fdebug[i] = NULL; + } +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_close_logfiles(struct soap *soap) +{ int i; + for (i = 0; i < SOAP_MAXLOGS; i++) + soap_close_logfile(soap, i); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +static void +soap_set_logfile(struct soap *soap, int i, const char *logfile) +{ char *s = NULL; + soap_close_logfile(soap, i); + if (soap->logfile[i]) + SOAP_FREE(soap, (void*)soap->logfile[i]); + if (logfile) + if ((s = (char*)SOAP_MALLOC(soap, strlen(logfile) + 1))) + strcpy(s, logfile); + soap->logfile[i] = s; +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_recv_logfile(struct soap *soap, const char *logfile) +{ soap_set_logfile(soap, SOAP_INDEX_RECV, logfile); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_sent_logfile(struct soap *soap, const char *logfile) +{ soap_set_logfile(soap, SOAP_INDEX_SENT, logfile); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_test_logfile(struct soap *soap, const char *logfile) +{ soap_set_logfile(soap, SOAP_INDEX_TEST, logfile); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_copy(struct soap *soap) +{ return soap_copy_context((struct soap*)malloc(sizeof(struct soap)), soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_copy_context(struct soap *copy, struct soap *soap) +{ if (copy) + { register struct soap_plugin *p; + memcpy(copy, soap, sizeof(struct soap)); + copy->copy = 1; + copy->user = NULL; + copy->error = SOAP_OK; + copy->userid = NULL; + copy->passwd = NULL; + copy->nlist = NULL; + copy->blist = NULL; + copy->clist = NULL; + copy->alist = NULL; + copy->attributes = NULL; +#ifdef WITH_FAST + copy->labbuf = NULL; + copy->lablen = 0; + copy->labidx = 0; +#endif +#ifdef SOAP_DEBUG + soap_init_mht(copy); +#endif + copy->local_namespaces = NULL; +#ifndef WITH_NOIDREF + soap_init_iht(copy); + soap_init_pht(copy); +#endif + copy->header = NULL; + copy->fault = NULL; + copy->action = NULL; +#ifndef WITH_LEAN +#ifdef WITH_COOKIES + copy->cookies = soap_copy_cookies(copy); +#else + copy->cookies = NULL; +#endif +#endif +#ifdef SOAP_DEBUG + soap_init_logs(copy); + soap_set_recv_logfile(copy, soap->logfile[SOAP_INDEX_RECV]); + soap_set_sent_logfile(copy, soap->logfile[SOAP_INDEX_SENT]); + soap_set_test_logfile(copy, soap->logfile[SOAP_INDEX_TEST]); +#endif + copy->plugins = NULL; + for (p = soap->plugins; p; p = p->next) + { register struct soap_plugin *q = (struct soap_plugin*)SOAP_MALLOC(copy, sizeof(struct soap_plugin)); + if (!q) + return NULL; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying plugin '%s'\n", p->id)); + *q = *p; + if (p->fcopy && (soap->error = p->fcopy(copy, q, p))) + { SOAP_FREE(copy, q); + return NULL; + } + q->next = copy->plugins; + copy->plugins = q; + } + } + else + soap->error = SOAP_EOM; + return copy; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_init(struct soap *soap) +{ soap->version = 0; + soap_imode(soap, SOAP_IO_DEFAULT); + soap_omode(soap, SOAP_IO_DEFAULT); + soap->copy = 0; + soap->plugins = NULL; + soap->user = NULL; + soap->userid = NULL; + soap->passwd = NULL; +#ifndef WITH_NOHTTP + soap->fpost = http_post; + soap->fget = http_get; + soap->fform = NULL; + soap->fposthdr = http_post_header; + soap->fresponse = http_response; + soap->fparse = http_parse; + soap->fparsehdr = http_parse_header; +#endif + soap->fconnect = NULL; + soap->fdisconnect = NULL; +#ifndef WITH_NOIO +#ifndef WITH_IPV6 + soap->fresolve = tcp_gethost; +#else + soap->fresolve = NULL; +#endif + soap->faccept = tcp_accept; + soap->fopen = tcp_connect; + soap->fclose = tcp_disconnect; + soap->fclosesocket = tcp_closesocket; + soap->fshutdownsocket = tcp_shutdownsocket; + soap->fsend = fsend; + soap->frecv = frecv; + soap->fpoll = soap_poll; +#else + soap->fopen = NULL; + soap->fclose = NULL; + soap->fpoll = NULL; +#endif +#ifndef WITH_LEANER + soap->fprepareinit = NULL; + soap->fpreparesend = NULL; + soap->fpreparerecv = NULL; + soap->fpreparefinal = NULL; +#endif + soap->fseterror = NULL; + soap->fignore = NULL; + soap->fserveloop = NULL; + soap->fplugin = fplugin; +#ifndef WITH_LEANER + soap->fdimereadopen = NULL; + soap->fdimewriteopen = NULL; + soap->fdimereadclose = NULL; + soap->fdimewriteclose = NULL; + soap->fdimeread = NULL; + soap->fdimewrite = NULL; +#endif + soap->float_format = "%.8g"; /* .8 preserves single FP precision as much as possible, but might not be very efficient */ + soap->double_format = "%.17lg"; /* .17 preserves double FP precision as much as possible, but might not be very efficient */ + soap->dime_id_format = "cid:id%d"; /* default DIME id format */ + soap->http_version = "1.1"; + soap->actor = NULL; + soap->max_keep_alive = SOAP_MAXKEEPALIVE; + soap->keep_alive = 0; + soap->recv_timeout = 0; + soap->send_timeout = 0; + soap->connect_timeout = 0; + soap->accept_timeout = 0; + soap->socket_flags = 0; + soap->connect_flags = 0; + soap->bind_flags = 0; + soap->accept_flags = 0; + soap->ip = 0; +#ifdef WITH_FAST + soap->labbuf = NULL; + soap->lablen = 0; + soap->labidx = 0; +#endif + soap->encodingStyle = SOAP_STR_EOS; +#ifndef WITH_NONAMESPACES + soap->namespaces = namespaces; +#else + soap->namespaces = NULL; +#endif + soap->local_namespaces = NULL; + soap->nlist = NULL; + soap->blist = NULL; + soap->clist = NULL; + soap->alist = NULL; + soap->attributes = NULL; + soap->header = NULL; + soap->fault = NULL; + soap->master = SOAP_INVALID_SOCKET; + soap->socket = SOAP_INVALID_SOCKET; + soap->os = NULL; + soap->is = NULL; +#ifndef WITH_LEANER + soap->dom = NULL; + soap->dime.list = NULL; + soap->dime.first = NULL; + soap->dime.last = NULL; + soap->mime.list = NULL; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = NULL; + soap->mime.start = NULL; + soap->xlist = NULL; +#endif +#ifndef UNDER_CE + soap->recvfd = 0; + soap->sendfd = 1; +#else + soap->recvfd = stdin; + soap->sendfd = stdout; +#endif + soap->host[0] = '\0'; + soap->port = 0; + soap->action = NULL; + soap->proxy_host = NULL; + soap->proxy_port = 8080; + soap->proxy_userid = NULL; + soap->proxy_passwd = NULL; + soap->authrealm = NULL; + soap->prolog = NULL; +#ifdef WITH_OPENSSL + soap->fsslauth = ssl_auth_init; + soap->fsslverify = ssl_verify_callback; + soap->bio = NULL; + soap->ssl = NULL; + soap->ctx = NULL; + soap->require_server_auth = 0; + soap->require_client_auth = 0; + soap->rsa = 0; + soap->keyfile = NULL; + soap->password = NULL; + soap->dhfile = NULL; + soap->cafile = NULL; + soap->capath = NULL; + soap->crlfile = NULL; + soap->randfile = NULL; + soap->session = NULL; +#endif +#ifdef WITH_ZLIB + soap->zlib_state = SOAP_ZLIB_NONE; + soap->zlib_in = SOAP_ZLIB_NONE; + soap->zlib_out = SOAP_ZLIB_NONE; + soap->d_stream.zalloc = NULL; + soap->d_stream.zfree = NULL; + soap->d_stream.opaque = NULL; + soap->z_level = 6; +#endif +#ifndef WITH_LEAN + soap->c14ninclude = NULL; + soap->c14nexclude = NULL; + soap->cookies = NULL; + soap->cookie_domain = NULL; + soap->cookie_path = NULL; + soap->cookie_max = 32; +#endif +#ifdef SOAP_DEBUG + soap_init_mht(soap); + soap_init_logs(soap); + soap_set_recv_logfile(soap, "RECV.log"); + soap_set_sent_logfile(soap, "SENT.log"); + soap_set_test_logfile(soap, NULL); +#endif +#ifdef WMW_RPM_IO + soap->rpmreqid = NULL; +#endif +#ifdef PALM + palmNetLibOpen(); +#endif +#ifndef WITH_NOIDREF + soap_init_iht(soap); + soap_init_pht(soap); +#endif + soap_begin(soap); +#ifdef SOAP_DEBUG + soap_set_test_logfile(soap, "TEST.log"); +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_init1(struct soap *soap, soap_mode mode) +{ soap_init2(soap, mode, mode); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_init2(struct soap *soap, soap_mode imode, soap_mode omode) +{ soap_init(soap); + soap_imode(soap, imode); + soap_omode(soap, omode); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_begin(struct soap *soap) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing\n")); + if (!soap->keep_alive) + { soap->buflen = 0; + soap->bufidx = 0; + } + soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0); + soap->null = 0; + soap->position = 0; + soap->encoding = 0; + soap->mustUnderstand = 0; + soap->mode = 0; + soap->ns = 0; + soap->part = SOAP_END; + soap->alloced = 0; + soap->count = 0; + soap->length = 0; + soap->cdata = 0; + soap->error = SOAP_OK; + soap->peeked = 0; + soap->ahead = 0; + soap->idnum = 0; + soap->level = 0; + soap->endpoint[0] = '\0'; +#ifndef WITH_LEANER + soap->dime.chunksize = 0; + soap->dime.buflen = 0; +#endif + soap_free(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_end(struct soap *soap) +{ register struct soap_clist *cp; + soap_free(soap); + soap_dealloc(soap, NULL); + while (soap->clist) + { cp = soap->clist->next; + SOAP_FREE(soap, soap->clist); + soap->clist = cp; + } + soap_closesock(soap); +#ifdef SOAP_DEBUG + soap_close_logfiles(soap); +#endif +#ifdef PALM + palmNetLibClose(); +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_namespaces(struct soap *soap, struct Namespace *p) +{ register struct Namespace *ns = soap->local_namespaces; + register struct soap_nlist *np, *nq, *nr; + register unsigned int level = soap->level; + soap->namespaces = p; + soap->local_namespaces = NULL; + soap_set_local_namespaces(soap); + /* reverse the namespace list */ + np = soap->nlist; + soap->nlist = NULL; + if (np) + { nq = np->next; + np->next = NULL; + while (nq) + { nr = nq->next; + nq->next = np; + np = nq; + nq = nr; + } + } + /* then push on new stack */ + while (np) + { register const char *s; + soap->level = np->level; /* preserve element nesting level */ + s = np->ns; + if (!s && np->index >= 0 && ns) + { s = ns[np->index].out; + if (!s) + s = ns[np->index].ns; + } + if (s && soap_push_namespace(soap, np->id, s)) + return soap->error; + nq = np; + np = np->next; + SOAP_FREE(soap, nq); + } + if (ns) + { register int i; + for (i = 0; ns[i].id; i++) + { if (ns[i].out) + { SOAP_FREE(soap, ns[i].out); + ns[i].out = NULL; + } + } + SOAP_FREE(soap, ns); + } + soap->level = level; /* restore level */ + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_local_namespaces(struct soap *soap) +{ if (soap->namespaces && !soap->local_namespaces) + { register const struct Namespace *ns1; + register struct Namespace *ns2; + register size_t n = 1; + for (ns1 = soap->namespaces; ns1->id; ns1++) + n++; + n *= sizeof(struct Namespace); + ns2 = (struct Namespace*)SOAP_MALLOC(soap, n); + if (ns2) + { memcpy(ns2, soap->namespaces, n); + if (ns2[0].ns) + { if (!strcmp(ns2[0].ns, soap_env1)) + soap->version = 1; + else + soap->version = 2; + } + soap->local_namespaces = ns2; + } + } +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +#ifndef PALM_1 +SOAP_FMAC1 +const char * +SOAP_FMAC2 +soap_strsearch(const char *big, const char *little) +{ size_t n = strlen(little); + const char *s = big; + while (s) + { if (!strncmp(s, little, n) && (s[n] == '\0' || s[n] == ' ')) + return s; + s = strchr(s, ' '); + if (s) + s++; + } + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static struct soap_nlist * +soap_lookup_ns(struct soap *soap, const char *tag, size_t n) +{ register struct soap_nlist *np; + for (np = soap->nlist; np; np = np->next) + { if (!strncmp(np->id, tag, n) && !np->id[n]) + return np; + } + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static struct soap_nlist * +soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized) +{ register struct soap_nlist *np; + size_t n, k; + if (soap_strsearch(soap->c14nexclude, id)) + return NULL; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push namespace binding (level=%u) '%s' '%s'\n", soap->level, id, ns?ns:"")); + if (!utilized) + { for (np = soap->nlist; np; np = np->next) + { if (!strcmp(np->id, id) && (!np->ns || !strcmp(np->ns, ns))) + break; + } + if (np) + { if (np->index == 1) + utilized = np->index; + else + return NULL; + } + } + n = strlen(id); + if (ns) + k = strlen(ns); + else + k = 0; + np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k + 1); + if (!np) + { soap->error = SOAP_EOM; + return NULL; + } + np->next = soap->nlist; + soap->nlist = np; + strcpy(np->id, id); + if (ns) + { np->ns = np->id + n + 1; + strcpy(np->ns, ns); + } + else + np->ns = NULL; + np->level = soap->level; + np->index = utilized; + return np; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static void +soap_utilize_ns(struct soap *soap, const char *tag, size_t n) +{ register struct soap_nlist *np = soap_lookup_ns(soap, tag, n); + if (np) + { if (np->index == 0) + soap_push_ns(soap, np->id, np->ns, 1); + } + else + { strncpy(soap->tmpbuf, tag, n); + soap->tmpbuf[n] = '\0'; + soap_push_ns(soap, soap->tmpbuf, NULL, 1); + } +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static void +soap_pop_ns(struct soap *soap) +{ soap_pop_namespace(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element(struct soap *soap, const char *tag, int id, const char *type) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element begin tag='%s' id='%d' type='%s'\n", tag, id, type?type:"")); +#ifdef WITH_DOM + if (soap->mode & SOAP_XML_DOM) + { register struct soap_dom_element *elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element)); + if (!elt) + return soap->error = SOAP_EOM; + elt->soap = soap; + elt->next = NULL; + elt->prnt = soap->dom; + elt->name = soap_strdup(soap, tag); + elt->elts = NULL; + elt->atts = NULL; + elt->nstr = NULL; + elt->data = NULL; + elt->wide = NULL; + elt->node = NULL; + elt->type = 0; + elt->head = NULL; + elt->tail = NULL; + if (soap->dom) + { struct soap_dom_element *p = soap->dom->elts; + if (p) + { while (p->next) + p = p->next; + p->next = elt; + } + else + soap->dom->elts = elt; + } + soap->dom = elt; + } + else + { +#endif + soap->level++; +#ifndef WITH_LEAN + if (!soap->ns) + { if (!(soap->mode & SOAP_XML_CANONICAL) + && soap_send(soap, soap->prolog ? soap->prolog : "\n")) + return soap->error; + } + else if (soap->mode & SOAP_XML_INDENT) + { if (soap->ns == 1 && soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1)) + return soap->error; + soap->body = 1; + } +#endif + if (soap_send_raw(soap, "<", 1) + || soap_send(soap, tag)) + return soap->error; +#ifdef WITH_DOM + } +#endif + if (!soap->ns) + { struct Namespace *ns; + for (ns = soap->local_namespaces; ns && ns->id; ns++) + { if (*ns->id && (ns->out || ns->ns)) + { sprintf(soap->tmpbuf, "xmlns:%s", ns->id); + if (soap_attribute(soap, soap->tmpbuf, ns->out ? ns->out : ns->ns)) + return soap->error; + } + } + } + soap->ns = 1; /* start with 0 or 2, but should be one to continue */ +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { const char *s = strchr(tag, ':'); + if (s) + soap_utilize_ns(soap, tag, s - tag); + } +#endif + if (id > 0) + { sprintf(soap->tmpbuf, "_%d", id); + if (soap_attribute(soap, "id", soap->tmpbuf)) + return soap->error; + } + if (type && *type) + { if (soap_attribute(soap, "xsi:type", type)) + return soap->error; +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { const char *s = strchr(type, ':'); + if (s) + soap_utilize_ns(soap, type, s - type); + } +#endif + } + if (soap->null && soap->position > 0) + { int i; + sprintf(soap->tmpbuf, "[%d", soap->positions[0]); + for (i = 1; i < soap->position; i++) + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), ",%d", soap->positions[i]); + strcat(soap->tmpbuf, "]"); + if (soap_attribute(soap, "SOAP-ENC:position", soap->tmpbuf)) + return soap->error; + } + if (soap->mustUnderstand) + { if (soap->actor && *soap->actor) + { if (soap_attribute(soap, soap->version == 2 ? "SOAP-ENV:role" : "SOAP-ENV:actor", soap->actor)) + return soap->error; + } + if (soap_attribute(soap, "SOAP-ENV:mustUnderstand", soap->version == 2 ? "true" : "1")) + return soap->error; + soap->mustUnderstand = 0; + } + if (soap->encoding) + { if (soap->encodingStyle && soap->local_namespaces) + { if (!*soap->encodingStyle) + { if (soap->local_namespaces[1].out) + soap->encodingStyle = soap->local_namespaces[1].out; + else + soap->encodingStyle = soap->local_namespaces[1].ns; + } + if (soap_attribute(soap, "SOAP-ENV:encodingStyle", soap->encodingStyle)) + return soap->error; + } + soap->encoding = 0; + } + soap->null = 0; + soap->position = 0; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_begin_out(struct soap *soap, const char *tag, int id, const char *type) +{ if (*tag == '-') + return SOAP_OK; + if (soap_element(soap, tag, id, type)) + return soap->error; + return soap_element_start_end_out(soap, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +#ifndef HAVE_STRRCHR +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_strrchr(const char *s, int t) +{ register char *r = NULL; + while (*s) + if (*s++ == t) + r = (char*)s - 1; + return r; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +#ifndef HAVE_STRTOL +SOAP_FMAC1 +long +SOAP_FMAC2 +soap_strtol(const char *s, char **t, int b) +{ register long n = 0; + register int c; + while (*s > 0 && *s <= 32) + s++; + if (b == 10) + { short neg = 0; + if (*s == '-') + { s++; + neg = 1; + } + else if (*s == '+') + s++; + while ((c = *s) && c >= '0' && c <= '9') + { if (n >= 214748364 && (n > 214748364 || c >= '8')) + break; + n *= 10; + n += c - '0'; + s++; + } + if (neg) + n = -n; + } + else /* b == 16 and value is always positive */ + { while ((c = *s)) + { if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'F') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'f') + c -= 'a' - 10; + if (n > 0x07FFFFFF) + break; + n <<= 4; + n += c; + s++; + } + } + if (t) + *t = (char*)s; + return n; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +#ifndef HAVE_STRTOUL +SOAP_FMAC1 +unsigned long +SOAP_FMAC2 +soap_strtoul(const char *s, char **t, int b) +{ unsigned long n = 0; + register int c; + while (*s > 0 && *s <= 32) + s++; + if (b == 10) + { if (*s == '+') + s++; + while ((c = *s) && c >= '0' && c <= '9') + { if (n >= 429496729 && (n > 429496729 || c >= '6')) + break; + n *= 10; + n += c - '0'; + s++; + } + } + else /* b == 16 */ + { while ((c = *s)) + { if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'F') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'f') + c -= 'a' - 10; + if (n > 0x0FFFFFFF) + break; + n <<= 4; + n += c; + s++; + } + } + if (t) + *t = (char*)s; + return n; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_array_begin_out(struct soap *soap, const char *tag, int id, const char *type, const char *offset) +{ if (soap_element(soap, tag, id, "SOAP-ENC:Array")) + return soap->error; + if (soap->version == 2) + { const char *s; + s = soap_strrchr(type, '['); + if ((size_t)(s - type) < sizeof(soap->tmpbuf)) + { strncpy(soap->tmpbuf, type, s - type); + soap->tmpbuf[s - type] = '\0'; + if (type && *type && (soap_attribute(soap, "SOAP-ENC:itemType", soap->tmpbuf))) + return soap->error; + if (s && (soap_attribute(soap, "SOAP-ENC:arraySize", s + 1))) + return soap->error; + } + } + else + { if (offset && (soap_attribute(soap, "SOAP-ENC:offset", offset))) + return soap->error; + if (type && *type && (soap_attribute(soap, "SOAP-ENC:arrayType", type))) + return soap->error; + } +#ifndef WITH_LEAN + if (type && *type && (soap->mode & SOAP_XML_CANONICAL)) + { const char *s = strchr(type, ':'); + if (s) + soap_utilize_ns(soap, type, s - type); + } +#endif + return soap_element_start_end_out(soap, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_start_end_out(struct soap *soap, const char *tag) +{ register struct soap_attribute *tp; +#ifdef WITH_DOM + register struct soap_dom_attribute **att; + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { att = &soap->dom->atts; + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible) + { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); + if (!*att) + return soap->error = SOAP_EOM; + (*att)->next = NULL; + (*att)->nstr = NULL; + (*att)->name = soap_strdup(soap, tp->name); + (*att)->data = soap_strdup(soap, tp->value); + (*att)->wide = NULL; + (*att)->soap = soap; + tp->visible = 0; + } + } + return SOAP_OK; + } +#endif +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { struct soap_nlist *np; + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible && tp->name) + { const char *s = strchr(tp->name, ':'); + if (s) + soap_utilize_ns(soap, tp->name, s - tp->name); + } + } + for (np = soap->nlist; np; np = np->next) + { if (np->index == 1 && np->ns) + { sprintf(soap->tmpbuf, "xmlns:%s", np->id); + soap_set_attr(soap, soap->tmpbuf, np->ns); + np->index = 2; + } + } + } +#endif + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible) + { if (soap_send(soap, " ") || soap_send(soap, tp->name)) + return soap->error; + if (tp->visible == 2 && tp->value) + if (soap_send_raw(soap, "=\"", 2) + || soap_string_out(soap, tp->value, 1) + || soap_send_raw(soap, "\"", 1)) + return soap->error; + tp->visible = 0; + } + } + if (tag) + { +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { if (soap_send_raw(soap, ">", 1) + || soap_element_end_out(soap, tag)) + return soap->error; + } + else +#endif + soap->level--; /* decrement level just before /> */ + if (soap_send_raw(soap, "/>", 2)) + return soap->error; + return SOAP_OK; + } + return soap_send_raw(soap, ">", 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_end_out(struct soap *soap, const char *tag) +{ if (*tag == '-') + return SOAP_OK; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element ending tag='%s'\n", tag)); +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { if (soap->dom->prnt) + soap->dom = soap->dom->prnt; + return SOAP_OK; + } +#endif +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + soap_pop_ns(soap); + if (soap->mode & SOAP_XML_INDENT) + { if (!soap->body) + { if (soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1)) + return soap->error; + } + soap->body = 0; + } +#endif + if (soap_send_raw(soap, "error; + soap->level--; /* decrement level just before > */ + return soap_send_raw(soap, ">", 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_ref(struct soap *soap, const char *tag, int id, int href) +{ register int n = 0; + if (soap->version == 2) + n = 1; + sprintf(soap->href, "#_%d", href); + return soap_element_href(soap, tag, id, "href" + n, soap->href + n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_href(struct soap *soap, const char *tag, int id, const char *ref, const char *val) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element '%s' reference %s='%s'\n", tag, ref, val)); + if (soap_element(soap, tag, id, NULL) + || soap_attribute(soap, ref, val) + || soap_element_start_end_out(soap, tag)) + return soap->error; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_null(struct soap *soap, const char *tag, int id, const char *type) +{ struct soap_attribute *tp; + for (tp = soap->attributes; tp; tp = tp->next) + if (tp->visible) + break; + if (tp || (soap->version == 2 && soap->position > 0) || id > 0 || (soap->mode & SOAP_XML_NIL)) + { if (soap_element(soap, tag, id, type)) + return soap->error; + if (soap->part != SOAP_IN_HEADER && soap->encodingStyle) + if (soap_attribute(soap, "xsi:nil", "true")) + return soap->error; + return soap_element_start_end_out(soap, tag); + } + soap->null = 1; + soap->position = 0; + soap->mustUnderstand = 0; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_id(struct soap *soap, const char *tag, int id, const void *p, const struct soap_array *a, int n, const char *type, int t) +{ if (!p || (a && !a->__ptr)) + { soap_element_null(soap, tag, id, type); + return -1; + } +#ifndef WITH_NOIDREF + if (soap->mode & SOAP_XML_TREE) + return 0; + if (id < 0) + { struct soap_plist *pp; + if (a) + id = soap_array_pointer_lookup(soap, p, a, n, t, &pp); + else + id = soap_pointer_lookup(soap, p, t, &pp); + if (id) + { if (soap_is_embedded(soap, pp)) + { soap_element_ref(soap, tag, 0, id); + return -1; + } + if (soap_is_single(soap, pp)) + return 0; + soap_set_embedded(soap, pp); + } + } + return id; +#else + return 0; +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_result(struct soap *soap, const char *tag) +{ if (soap->version == 2 && soap->encodingStyle) + if (soap_element(soap, "SOAP-RPC:result", 0, NULL) + || soap_attribute(soap, "xmlns:SOAP-RPC", soap_rpc) + || soap_element_start_end_out(soap, NULL) + || soap_string_out(soap, tag, 0) + || soap_element_end_out(soap, "SOAP-RPC:result")) + return soap->error; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_attribute(struct soap *soap, const char *name, const char *value) +{ +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { register struct soap_dom_attribute *a = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); + a->next = soap->dom->atts; + a->nstr = NULL; + a->name = soap_strdup(soap, name); + a->data = soap_strdup(soap, value); + a->wide = NULL; + a->soap = soap; + soap->dom->atts = a; + return SOAP_OK; + } +#endif +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { /* TODO: consider using this code to handle default namespace + if (!strncmp(name, "xmlns", 5) && (name[5] == ':' || name[5] == '\0')) + { if (name[5] == ':') + soap_push_ns(soap, name + 6, value, 0); + else + soap_push_ns(soap, "", value, 0); + } + */ + if (!strncmp(name, "xmlns:", 6)) + soap_push_ns(soap, name + 6, value, 0); + else if (soap_set_attr(soap, name, value)) + return soap->error; + } + else +#endif + { if (soap_send(soap, " ") || soap_send(soap, name)) + return soap->error; + if (value) + if (soap_send_raw(soap, "=\"", 2) + || soap_string_out(soap, value, 1) + || soap_send_raw(soap, "\"", 1)) + return soap->error; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_begin_in(struct soap *soap, const char *tag, int nillable) +{ if (!soap_peek_element(soap)) + { if (soap->other) + return soap->error = SOAP_TAG_MISMATCH; + if (tag && *tag == '-') + return SOAP_OK; + if (!(soap->error = soap_match_tag(soap, soap->tag, tag))) + { soap->peeked = 0; + if (soap->body) + soap->level++; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:"" )); + if (!nillable && soap->null && (soap->mode & SOAP_XML_STRICT)) + return soap->error = SOAP_NULL; + } + } + else if (soap->error == SOAP_NO_TAG && tag && *tag == '-') + soap->error = SOAP_OK; + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_end_in(struct soap *soap, const char *tag) +{ register soap_wchar c; + register char *s; + register const char *t; + register int n = 0; + if (tag && *tag == '-') + return SOAP_OK; + soap->level--; + soap_pop_namespace(soap); +#ifdef WITH_DOM + /* this whitespace or mixed content is not insignificant for DOM */ + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { if (!soap->peeked && !soap_string_in(soap, 3, -1, -1)) + return soap->error; + if (soap->dom->prnt) + soap->dom = soap->dom->prnt; + } +#endif + if (soap->peeked) + { if (soap->error == SOAP_NO_TAG) + soap->error = SOAP_OK; + if (*soap->tag) + n++; + soap->peeked = 0; + } + do + { while (((c = soap_get(soap)) != SOAP_TT)) + { if ((int)c == EOF) + return soap->error = SOAP_EOF; + if (c == SOAP_LT) + n++; + else if (c == '/') + { c = soap_get(soap); + if (c == SOAP_GT) + n--; + else + soap_unget(soap, c); + } + } + } while (n--); + s = soap->tag; + while (soap_notblank(c = soap_get(soap))) + *s++ = (char)c; + *s = '\0'; + if ((int)c == EOF) + return soap->error = SOAP_EOF; + while (soap_blank(c)) + c = soap_get(soap); + if (c != SOAP_GT) + return soap->error = SOAP_SYNTAX_ERROR; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:"")); + if (!tag || !*tag) + return SOAP_OK; + if ((s = strchr(soap->tag, ':'))) + s++; + else + s = soap->tag; + if ((t = strchr(tag, ':'))) + t++; + else + t = tag; + if (!SOAP_STRCMP(s, t)) + return SOAP_OK; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element tag name does not match\n")); + return soap->error = SOAP_SYNTAX_ERROR; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char * +SOAP_FMAC2 +soap_attr_value(struct soap *soap, const char *name, int flag) +{ register struct soap_attribute *tp; + for (tp = soap->attributes; tp; tp = tp->next) + if (!soap_match_tag(soap, tp->name, name)) + break; + if (tp && tp->visible == 2) + { if (flag == 2 && (soap->mode & SOAP_XML_STRICT)) + soap->error = SOAP_PROHIBITED; + else + return tp->value; + } + else if (flag == 1 && (soap->mode & SOAP_XML_STRICT)) + soap->error = SOAP_REQUIRED; + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_attr(struct soap *soap, const char *name, const char *value) +{ register struct soap_attribute *tp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set attribute %s='%s'\n", name, value?value:"")); + for (tp = soap->attributes; tp; tp = tp->next) + { if (!strcmp(tp->name, name)) + break; + } + if (!tp) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute %s\n", name)); + if (!(tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(name)))) + return soap->error = SOAP_EOM; + tp->ns = NULL; +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { struct soap_attribute **tpp = &soap->attributes; + const char *s = strchr(name, ':'); + if (!strncmp(name, "xmlns", 5)) + { for (; *tpp; tpp = &(*tpp)->next) + if (strncmp((*tpp)->name, "xmlns", 5) || strcmp((*tpp)->name + 5, name + 5) > 0) + break; + } + else if (!s) + { for (; *tpp; tpp = &(*tpp)->next) + if (strncmp((*tpp)->name, "xmlns", 5) && ((*tpp)->ns || strcmp((*tpp)->name, name) > 0)) + break; + } + else + { int k; + for (; *tpp; tpp = &(*tpp)->next) + { if (!strncmp((*tpp)->name, "xmlns:", 6) && !strncmp((*tpp)->name + 6, name, s - name) && !(*tpp)->name[6 + s - name]) + { if (!tp->ns) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Canonicalization: prefix %s=%p(%s)\n", name, (*tpp)->ns, (*tpp)->ns)); + tp->ns = (*tpp)->ns; + } + } + else if (strncmp((*tpp)->name, "xmlns", 5) && (*tpp)->ns && tp->ns && ((k = strcmp((*tpp)->ns, tp->ns)) > 0 || (!k && strcmp((*tpp)->name, name) > 0))) + break; + } + } + tp->next = *tpp; + *tpp = tp; + } + else +#endif + { tp->next = soap->attributes; + soap->attributes = tp; + } + strcpy(tp->name, name); + tp->value = NULL; + } + else if (value && tp->value && tp->size <= strlen(value)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute value of %s (free %p)\n", name, tp->value)); + SOAP_FREE(soap, tp->value); + tp->value = NULL; + tp->ns = NULL; + } + if (value) + { if (!tp->value) + { tp->size = strlen(value) + 1; + if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size))) + return soap->error = SOAP_EOM; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute value of %s (%p)\n", tp->name, tp->value)); + } + strcpy(tp->value, value); + if (!strncmp(tp->name, "xmlns:", 6)) + tp->ns = tp->value; + tp->visible = 2; +#ifndef WITH_LEAN + if (!strcmp(name, "wsu:Id")) + { soap->part = SOAP_BEGIN_SECURITY; + strncpy(soap->id, value, sizeof(soap->id)); + soap->id[sizeof(soap->id)-1] = '\0'; + } +#endif + } + else + tp->visible = 1; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_clr_attr(struct soap *soap) +{ register struct soap_attribute *tp; +#ifndef WITH_LEAN + if ((soap->mode & SOAP_XML_CANONICAL)) + { while (soap->attributes) + { tp = soap->attributes->next; + SOAP_FREE(soap, soap->attributes->value); + SOAP_FREE(soap, soap->attributes); + soap->attributes = tp; + } + } + else +#endif + { for (tp = soap->attributes; tp; tp = tp->next) + tp->visible = 0; + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +static int +soap_getattrval(struct soap *soap, char *s, size_t n, soap_wchar d) +{ register size_t i; + for (i = 0; i < n; i++) + { register soap_wchar c = soap_get(soap); + switch (c) + { + case SOAP_TT: + *s++ = '<'; + soap_unget(soap, '/'); + break; + case SOAP_LT: + *s++ = '<'; + break; + case SOAP_GT: + if (d == ' ') + { soap_unget(soap, c); + *s = '\0'; + return SOAP_OK; + } + *s++ = '>'; + break; + case SOAP_QT: + if (c == d) + { *s = '\0'; + return SOAP_OK; + } + *s++ = '"'; + break; + case SOAP_AP: + if (c == d) + { *s = '\0'; + return SOAP_OK; + } + *s++ = '\''; + break; + case '\t': + case '\n': + case '\r': + case ' ': + case '/': + if (d == ' ') + { soap_unget(soap, c); + *s = '\0'; + return SOAP_OK; + } + default: + if ((int)c == EOF) + return soap->error = SOAP_EOF; + *s++ = (char)c; + } + } + return soap->error = SOAP_EOM; +} +#endif + +/******************************************************************************/ +#ifdef WITH_FAST +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_store_lab(struct soap *soap, const char *s, size_t n) +{ soap->labidx = 0; + return soap_append_lab(soap, s, n); +} +#endif +#endif + +/******************************************************************************/ +#ifdef WITH_FAST +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_append_lab(struct soap *soap, const char *s, size_t n) +{ if (soap->labidx + n >= soap->lablen) + { register char *t = soap->labbuf; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enlarging look-aside buffer to append data, old size=%lu", (unsigned long)soap->lablen)); + if (soap->lablen == 0) + soap->lablen = SOAP_LABLEN; + while (soap->labidx + n >= soap->lablen) + soap->lablen <<= 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, ", new size=%lu\n", (unsigned long)soap->lablen)); + soap->labbuf = (char*)SOAP_MALLOC(soap, soap->lablen); + if (!soap->labbuf) + { if (t) + SOAP_FREE(soap, t); + return soap->error = SOAP_EOM; + } + if (t) + { memcpy(soap->labbuf, t, soap->labidx); + SOAP_FREE(soap, t); + } + } + if (s) + { memcpy(soap->labbuf + soap->labidx, s, n); + soap->labidx += n; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_peek_element(struct soap *soap) +{ +#ifdef WITH_DOM + register struct soap_dom_attribute **att = NULL; + register char *lead = NULL; +#endif + register struct soap_attribute *tp; + const char *t; + register char *s; + register soap_wchar c; + register int i; + if (soap->peeked) + { if (!*soap->tag) + return soap->error = SOAP_NO_TAG; + return SOAP_OK; + } + soap->peeked = 1; + c = soap_getutf8(soap); +#ifdef WITH_DOM + /* whitespace leading to start tag is not insignificant for DOM */ + if (soap_blank(c)) + { soap->labidx = 0; + do + { if (soap_append_lab(soap, NULL, 0)) + return SOAP_EOM; + s = soap->labbuf + soap->labidx; + i = soap->lablen - soap->labidx; + soap->labidx = soap->lablen; + while (soap_blank(c) && i--) + { *s++ = c; + c = soap_getutf8(soap); + } + } + while (soap_blank(c)); + *s = '\0'; + lead = soap_strdup(soap, soap->labbuf); + } +#else + while (soap_blank(c)) + c = soap_getutf8(soap); +#endif + if (c != SOAP_LT) + { *soap->tag = '\0'; + if ((int)c == EOF) + return soap->error = SOAP_EOF; + soap_unget(soap, c); +#ifdef WITH_DOM + /* whitespace leading to end tag is not insignificant for DOM */ + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + soap->dom->tail = soap_strdup(soap, lead); +#endif + return soap->error = SOAP_NO_TAG; + } + s = soap->tag; + do c = soap_get1(soap); + while (soap_blank(c)); + i = sizeof(soap->tag); + while (c != '>' && c != '/' && soap_notblank(c)) + { if (--i > 0) + *s++ = (char)c; + c = soap_get1(soap); + } + while (soap_blank(c)) + c = soap_get1(soap); + *s = '\0'; + soap->id[0] = '\0'; + soap->href[0] = '\0'; + soap->type[0] = '\0'; + soap->arrayType[0] = '\0'; + soap->arraySize[0] = '\0'; + soap->arrayOffset[0] = '\0'; + soap->other = 0; + soap->root = -1; + soap->position = 0; + soap->null = 0; + soap->mustUnderstand = 0; +#ifdef WITH_DOM + if (soap->mode & SOAP_XML_DOM) + { register struct soap_dom_element *elt; + elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element)); + if (!elt) + return soap->error = SOAP_EOM; + elt->next = NULL; + elt->nstr = NULL; + elt->name = soap_strdup(soap, soap->tag); + elt->prnt = soap->dom; + elt->elts = NULL; + elt->atts = NULL; + elt->data = NULL; + elt->wide = NULL; + elt->type = 0; + elt->node = NULL; + elt->head = lead; + elt->tail = NULL; + elt->soap = soap; + if (soap->dom) + { struct soap_dom_element *p = soap->dom->elts; + if (p) + { while (p->next) + p = p->next; + p->next = elt; + } + else + soap->dom->elts = elt; + } + soap->dom = elt; + att = &elt->atts; + } +#endif + for (tp = soap->attributes; tp; tp = tp->next) + tp->visible = 0; + while ((int)c != EOF && c != '>' && c != '/') + { s = soap->tmpbuf; + i = sizeof(soap->tmpbuf); + while (c != '=' && c != '>' && c != '/' && soap_notblank(c)) + { if (--i > 0) + *s++ = (char)c; + c = soap_get1(soap); + } + *s = '\0'; + if (i == sizeof(soap->tmpbuf)) + return soap->error = SOAP_SYNTAX_ERROR; +#ifdef WITH_DOM + /* add attribute name to dom */ + if (att) + { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); + if (!*att) + return soap->error = SOAP_EOM; + (*att)->next = NULL; + (*att)->nstr = NULL; + (*att)->name = soap_strdup(soap, soap->tmpbuf); + (*att)->data = NULL; + (*att)->wide = NULL; + (*att)->soap = soap; + } +#endif + if (!strncmp(soap->tmpbuf, "xmlns", 5)) + { if (soap->tmpbuf[5] == ':') + { soap->tmpbuf[5] = '\0'; + t = soap->tmpbuf + 6; + } + else if (soap->tmpbuf[5]) + t = NULL; + else + t = SOAP_STR_EOS; + } + else + t = NULL; + for (tp = soap->attributes; tp; tp = tp->next) + { if (!SOAP_STRCMP(tp->name, soap->tmpbuf)) + break; + } + if (!tp) + { tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(soap->tmpbuf)); + if (!tp) + return soap->error = SOAP_EOM; + strcpy(tp->name, soap->tmpbuf); + tp->value = NULL; + tp->size = 0; + tp->next = soap->attributes; + soap->attributes = tp; + } + while (soap_blank(c)) + c = soap_get1(soap); + if (c == '=') + { do c = soap_getutf8(soap); + while (soap_blank(c)); + if (c != SOAP_QT && c != SOAP_AP) + { soap_unget(soap, c); + c = ' '; /* blank delimiter */ + } + if (soap_getattrval(soap, tp->value, tp->size, c)) + { +#ifdef WITH_FAST + if (soap->error != SOAP_EOM) + return soap->error; + soap->error = SOAP_OK; + if (soap_store_lab(soap, tp->value, tp->size)) + return soap->error; + if (tp->value) + SOAP_FREE(soap, tp->value); + for (;;) + { if (soap_getattrval(soap, soap->labbuf + soap->labidx, soap->lablen - soap->labidx, c)) + { if (soap->error != SOAP_EOM) + return soap->error; + soap->error = SOAP_OK; + soap->labidx = soap->lablen; + if (soap_append_lab(soap, NULL, 0)) + return soap->error; + } + else + break; + } + if (soap->labidx) + tp->size = soap->lablen; + else + { tp->size = strlen(soap->labbuf) + 1; + if (tp->size < SOAP_LABLEN) + tp->size = SOAP_LABLEN; + } + if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size))) + return soap->error = SOAP_EOM; + strcpy(tp->value, soap->labbuf); +#else + size_t n; + if (soap->error != SOAP_EOM) + return soap->error; + soap->error = SOAP_OK; + if (soap_new_block(soap)) + return soap->error; + for (;;) + { if (!(s = (char*)soap_push_block(soap, SOAP_BLKLEN))) + return soap->error; + if (soap_getattrval(soap, s, SOAP_BLKLEN, c)) + { if (soap->error != SOAP_EOM) + return soap->error; + soap->error = SOAP_OK; + } + else + break; + } + n = tp->size + soap->blist->size; + if (!(s = (char*)SOAP_MALLOC(soap, n))) + return soap->error = SOAP_EOM; + if (tp->value) + { memcpy(s, tp->value, tp->size); + SOAP_FREE(soap, tp->value); + } + soap_save_block(soap, s + tp->size, 0); + tp->value = s; + tp->size = n; +#endif + } + do c = soap_get1(soap); + while (soap_blank(c)); + tp->visible = 2; /* seen this attribute w/ value */ +#ifdef WITH_DOM + if (att) + (*att)->data = soap_strdup(soap, tp->value); +#endif + } + else + tp->visible = 1; /* seen this attribute w/o value */ +#ifdef WITH_DOM + if (att) + att = &(*att)->next; +#endif + if (t && tp->value) + { if (soap_push_namespace(soap, t, tp->value)) + return soap->error; + tp->visible = 0; + } + } +#ifdef WITH_DOM + if (att) + { soap->dom->nstr = soap_current_namespace(soap, soap->tag); + for (att = &soap->dom->atts; *att; att = &(*att)->next) + (*att)->nstr = soap_current_namespace(soap, (*att)->name); + } +#endif + if ((int)c == EOF) + return soap->error = SOAP_EOF; + if (!(soap->body = (c != '/'))) + do c = soap_get1(soap); + while (soap_blank(c)); +#ifdef WITH_DOM + if (soap->mode & SOAP_XML_DOM) + { if (!soap->body && soap->dom->prnt) + soap->dom = soap->dom->prnt; + } +#endif + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible && tp->value) + { if (!strcmp(tp->name, "id")) + { *soap->id = '#'; + strncpy(soap->id + 1, tp->value, sizeof(soap->id) - 2); + soap->id[sizeof(soap->id)-1] = '\0'; + } + else if (!strcmp(tp->name, "href")) + { strncpy(soap->href, tp->value, sizeof(soap->href) - 1); + soap->href[sizeof(soap->href)-1] = '\0'; + } + else if ((soap->version == 2 || (soap->mode & SOAP_XML_GRAPH)) && !strcmp(tp->name, "ref")) + { *soap->href = '#'; + strncpy(soap->href + 1, tp->value, sizeof(soap->href) - 2); + soap->href[sizeof(soap->href)-1] = '\0'; + } + else if (!soap_match_tag(soap, tp->name, "xsi:type")) + { strncpy(soap->type, tp->value, sizeof(soap->type) - 1); + soap->type[sizeof(soap->type)-1] = '\0'; + } + else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:arrayType")) + { s = soap_strrchr(tp->value, '['); + if (s && (size_t)(s - tp->value) < sizeof(soap->arrayType)) + { strncpy(soap->arrayType, tp->value, s - tp->value); + soap->arrayType[s - tp->value] = '\0'; + strncpy(soap->arraySize, s, sizeof(soap->arraySize) - 1); + } + else + strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1); + soap->arraySize[sizeof(soap->arrayType)-1] = '\0'; + soap->arrayType[sizeof(soap->arrayType)-1] = '\0'; + } + else if (soap->version == 2 && !soap_match_tag(soap, tp->name, "SOAP-ENC:itemType")) + strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1); + else if (soap->version == 2 && !soap_match_tag(soap, tp->name, "SOAP-ENC:arraySize")) + strncpy(soap->arraySize, tp->value, sizeof(soap->arraySize) - 1); + else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:offset")) + strncpy(soap->arrayOffset, tp->value, sizeof(soap->arrayOffset)); + else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:position")) + soap->position = soap_getposition(tp->value, soap->positions); + else if (soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENC:root")) + soap->root = ((!strcmp(tp->value, "1") || !strcmp(tp->value, "true"))); + else if ((soap->version == 1 && !soap_match_tag(soap, tp->name, "SOAP-ENV:actor")) + || (soap->version == 2 && !soap_match_tag(soap, tp->name, "SOAP-ENV:role"))) + { if ((!soap->actor || strcmp(soap->actor, tp->value)) + && strcmp(tp->value, "http://schemas.xmlsoap.org/soap/actor/next") + && strcmp(tp->value, "http://www.w3.org/2003/05/soap-envelope/role/next")) + soap->other = 1; + } + else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand") + && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true"))) + soap->mustUnderstand = 1; + else if ((!soap_match_tag(soap, tp->name, "xsi:null") + || !soap_match_tag(soap, tp->name, "xsi:nil")) + && (!strcmp(tp->value, "1") + || !strcmp(tp->value, "true"))) + soap->null = 1; + } + } + return soap->error = SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_retry(struct soap *soap) +{ soap->error = SOAP_OK; + soap_revert(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_revert(struct soap *soap) +{ if (!soap->peeked) + { soap->peeked = 1; + if (soap->body) + soap->level--; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reverting last element (level=%u)\n", soap->level)); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_string_out(struct soap *soap, const char *s, int flag) +{ register const char *t; + register soap_wchar c; + register soap_wchar mask = 0xFFFFFF80UL; +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { soap->dom->data = soap_strdup(soap, s); + return SOAP_OK; + } +#endif + if (soap->mode & SOAP_C_UTFSTRING) + mask = 0; + t = s; + while ((c = *t++)) + { switch (c) + { + case 9: + if (flag) + { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, " ", 5)) + return soap->error; + s = t; + } + break; + case 10: + if (flag || !(soap->mode & SOAP_XML_CANONICAL)) + { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, " ", 5)) + return soap->error; + s = t; + } + break; + case 13: + if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, " ", 5)) + return soap->error; + s = t; + break; + case '&': + if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&", 5)) + return soap->error; + s = t; + break; + case '<': + if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "<", 4)) + return soap->error; + s = t; + break; + case '>': + if (!flag) + { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, ">", 4)) + return soap->error; + s = t; + } + break; + case '"': + if (flag) + { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, """, 6)) + return soap->error; + s = t; + } + break; + default: +#ifndef WITH_LEANER +#ifdef HAVE_MBTOWC + if (soap->mode & SOAP_C_MBSTRING) + { wchar_t wc; + register int m = mbtowc(&wc, t - 1, MB_CUR_MAX); + if (m > 0 && wc != c) + { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, wc)) + return soap->error; + s = t += m - 1; + continue; + } + } +#endif +#endif + if (c & mask) + { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned char)c)) + return soap->error; + s = t; + } + } + } + return soap_send_raw(soap, s, t - s - 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_string_in(struct soap *soap, int flag, long minlen, long maxlen) +{ register char *s; + char *t = NULL; + register size_t i; + register long l = 0; + register int n = 0; + register int m = 0; + register soap_wchar c; +#if !defined(WITH_LEANER) && defined(HAVE_WCTOMB) + char buf[MB_LEN_MAX > 8 ? MB_LEN_MAX : 8]; +#else + char buf[8]; +#endif + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading string content\n")); + if (soap->peeked) + { if (!soap->body) + return NULL; + if (*soap->tag) + { n = 1; + soap->peeked = 0; +#ifndef WITH_LEAN + t = soap->tmpbuf; + t[0] = '<'; + strncpy(t + 1, soap->tag, sizeof(soap->tmpbuf) - 1); + strncat(t, ">", sizeof(soap->tmpbuf)); + m = strlen(soap->tag) + 2; +#endif + } + } +#ifdef WITH_CDATA + if (!flag) + { register int state = 0; +#ifdef WITH_FAST + soap->labidx = 0; /* use look-aside buffer */ +#else + if (soap_new_block(soap)) + return NULL; +#endif + for (;;) + { +#ifdef WITH_FAST + register size_t k; + if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */ + return NULL; + s = soap->labbuf + soap->labidx; /* space to populate */ + k = soap->lablen - soap->labidx; /* number of bytes available */ + soap->labidx = soap->lablen; /* claim this space */ +#else + register size_t k = SOAP_BLKLEN; + if (!(s = (char*)soap_push_block(soap, k))) + return NULL; +#endif + for (i = 0; i < k; i++) + { if (m > 0) + { *s++ = *t++; /* copy multibyte characters */ + m--; + continue; + } + c = soap_getchar(soap); + if ((int)c == EOF) + goto end; + if (c >= 0x80 && !(soap->mode & SOAP_ENC_LATIN)) + { soap_unget(soap, c); + c = soap_getutf8(soap); + if (soap->mode & SOAP_C_UTFSTRING) + { if ((c & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP) + { c &= 0x7FFFFFFF; + t = buf; + if (c < 0x0800) + *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); + else + { if (c < 0x010000) + *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + else + { if (c < 0x200000) + *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + else + { if (c < 0x04000000) + *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + else + { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + } + *t++ = (char)(0x80 | (c & 0x3F)); + m = (int)(t - buf) - 1; + t = buf; + *s++ = *t++; + continue; + } + } + } + switch (state) + { case 1: + if (c == ']') + state = 4; + *s++ = c; + continue; + case 2: + if (c == '-') + state = 6; + *s++ = c; + continue; + case 3: + if (c == '?') + state = 8; + *s++ = c; + continue; + /* CDATA */ + case 4: + if (c == ']') + state = 5; + else + state = 1; + *s++ = c; + continue; + case 5: + if (c == '>') + state = 0; + else + state = 1; + *s++ = c; + continue; + /* comment */ + case 6: + if (c == '-') + state = 7; + else + state = 2; + *s++ = c; + continue; + case 7: + if (c == '>') + state = 0; + else + state = 2; + *s++ = c; + continue; + /* PI */ + case 8: + if (c == '>') + state = 0; + else + state = 3; + *s++ = c; + continue; + } + switch (c) + { + case '/': + if (n > 0) + { c = soap_getchar(soap); + if (c == '>') + n--; + soap_unget(soap, c); + } + *s++ = '/'; + break; + case '<': + c = soap_getchar(soap); + if (c == '/') + { if (n == 0) + { c = SOAP_TT; + goto end; + } + n--; + } + else if (c == '!') + { c = soap_getchar(soap); + if (c == '[') + { do c = soap_getchar(soap); + while ((int)c != EOF && c != '['); + if ((int)c == EOF) + goto end; + t = (char*)"![CDATA["; + m = 8; + state = 1; + } + else if (c == '-') + { if ((c = soap_getchar(soap)) == '-') + state = 2; + t = (char*)"!-"; + m = 2; + soap_unget(soap, c); + } + else + { t = (char*)"!"; + m = 1; + soap_unget(soap, c); + } + *s++ = '<'; + break; + } + else if (c == '?') + state = 3; + else + n++; + soap_unget(soap, c); + *s++ = '<'; + break; + case '>': + *s++ = '>'; + break; + case '"': + *s++ = '"'; + break; + default: +#ifndef WITH_LEANER +#ifdef HAVE_WCTOMB + if (soap->mode & SOAP_C_MBSTRING) + { m = wctomb(buf, c & 0x7FFFFFFF); + if (m >= 1 && m <= (int)MB_CUR_MAX) + { t = buf; + *s++ = *t++; + m--; + } + else + { *s++ = SOAP_UNKNOWN_CHAR; + m = 0; + } + } + else +#endif +#endif + *s++ = (char)(c & 0xFF); + } + l++; + if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); + soap->error = SOAP_LENGTH; + return NULL; + } + } + } + } +#endif +#ifdef WITH_FAST + soap->labidx = 0; /* use look-aside buffer */ +#else + if (soap_new_block(soap)) + return NULL; +#endif + for (;;) + { +#ifdef WITH_FAST + register size_t k; + if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */ + return NULL; + s = soap->labbuf + soap->labidx; /* space to populate */ + k = soap->lablen - soap->labidx; /* number of bytes available */ + soap->labidx = soap->lablen; /* claim this space */ +#else + register size_t k = SOAP_BLKLEN; + if (!(s = (char*)soap_push_block(soap, k))) + return NULL; +#endif + for (i = 0; i < k; i++) + { if (m > 0) + { *s++ = *t++; /* copy multibyte characters */ + m--; + continue; + } + if (soap->mode & SOAP_C_UTFSTRING) + { if (((c = soap_get(soap)) & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP) + { c &= 0x7FFFFFFF; + t = buf; + if (c < 0x0800) + *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); + else + { if (c < 0x010000) + *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + else + { if (c < 0x200000) + *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + else + { if (c < 0x04000000) + *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + else + { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + } + *t++ = (char)(0x80 | (c & 0x3F)); + m = (int)(t - buf) - 1; + t = buf; + *s++ = *t++; + continue; + } + } + else + c = soap_getutf8(soap); + switch (c) + { + case SOAP_TT: + if (n == 0) + goto end; + n--; + *s++ = '<'; + t = (char*)"/"; + m = 1; + break; + case SOAP_LT: + n++; + *s++ = '<'; + break; + case SOAP_GT: + *s++ = '>'; + break; + case SOAP_QT: + *s++ = '"'; + break; + case SOAP_AP: + *s++ = '\''; + break; + case '/': + if (n > 0) + { c = soap_get(soap); + if (c == SOAP_GT) + n--; + soap_unget(soap, c); + } + *s++ = '/'; + break; + case '<' | 0x80000000: + if (flag) + *s++ = '<'; + else + { *s++ = '&'; + t = (char*)"lt;"; + m = 3; + } + break; + case '>' | 0x80000000: + if (flag) + *s++ = '>'; + else + { *s++ = '&'; + t = (char*)"gt;"; + m = 3; + } + break; + case '&' | 0x80000000: + if (flag) + *s++ = '&'; + else + { *s++ = '&'; + t = (char*)"amp;"; + m = 4; + } + break; + case '"' | 0x80000000: + if (flag) + *s++ = '"'; + else + { *s++ = '&'; + t = (char*)"quot;"; + m = 5; + } + break; + case '\'' | 0x80000000: + if (flag) + *s++ = '\''; + else + { *s++ = '&'; + t = (char*)"apos;"; + m = 5; + } + break; + default: + if ((int)c == EOF) + goto end; +#ifndef WITH_LEANER +#ifdef HAVE_WCTOMB + if (soap->mode & SOAP_C_MBSTRING) + { m = wctomb(buf, c & 0x7FFFFFFF); + if (m >= 1 && m <= (int)MB_CUR_MAX) + { t = buf; + *s++ = *t++; + m--; + } + else + { *s++ = SOAP_UNKNOWN_CHAR; + m = 0; + } + } + else +#endif +#endif + *s++ = (char)(c & 0xFF); + } + l++; + if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); + soap->error = SOAP_LENGTH; + return NULL; + } + } + } +end: + soap_unget(soap, c); + *s = '\0'; +#ifdef WITH_FAST + t = soap_strdup(soap, soap->labbuf); +#else + soap_size_block(soap, i+1); + t = soap_save_block(soap, NULL, 0); +#endif + if ((soap->mode & SOAP_XML_STRICT) && l < minlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen)); + soap->error = SOAP_LENGTH; + return NULL; + } +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { if (flag == 3) + soap->dom->tail = t; + else + soap->dom->data = t; + } +#endif + if (flag == 2) + if (soap_s2QName(soap, t, &t)) + return NULL; + return t; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_wstring_out(struct soap *soap, const wchar_t *s, int flag) +{ const char *t; + char tmp; + register soap_wchar c; +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { wchar_t *r = (wchar_t*)s; + int n = 1; + while (*r++) + n++; + soap->dom->wide = r = (wchar_t*)soap_malloc(soap, n * sizeof(wchar_t)); + while (n--) + *r++ = *s++; + return SOAP_OK; + } +#endif + while ((c = *s++)) + { switch (c) + { + case 9: + if (flag) + t = " "; + else + t = "\t"; + break; + case 10: + if (flag || !(soap->mode & SOAP_XML_CANONICAL)) + t = " "; + else + t = "\n"; + break; + case 13: + t = " "; + break; + case '&': + t = "&"; + break; + case '<': + t = "<"; + break; + case '>': + if (flag) + t = ">"; + else + t = ">"; + break; + case '"': + if (flag) + t = """; + else + t = "\""; + break; + default: + if (c > 0 && c < 0x80) + { tmp = (char)c; + if (soap_send_raw(soap, &tmp, 1)) + return soap->error; + } + else if (soap_pututf8(soap, (unsigned long)c)) + return soap->error; + continue; + } + if (soap_send(soap, t)) + return soap->error; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +wchar_t * +SOAP_FMAC2 +soap_wstring_in(struct soap *soap, int flag, long minlen, long maxlen) +{ wchar_t *s; + register int i, n = 0; + register long l = 0; + register soap_wchar c; + const char *t = NULL; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading wide string content\n")); + if (soap->peeked) + { if (!soap->body) + return NULL; + if (*soap->tag) + { n = 1; + soap->peeked = 0; + } + } + if (soap_new_block(soap)) + return NULL; + for (;;) + { if (!(s = (wchar_t*)soap_push_block(soap, sizeof(wchar_t)*SOAP_BLKLEN))) + return NULL; + for (i = 0; i < SOAP_BLKLEN; i++) + { if (t) + { *s++ = (wchar_t)*t++; + if (!*t) + t = NULL; + continue; + } + c = soap_getutf8(soap); + switch (c) + { + case SOAP_TT: + if (n == 0) + goto end; + n--; + *s++ = '<'; + soap_unget(soap, '/'); + break; + case SOAP_LT: + n++; + *s++ = '<'; + break; + case SOAP_GT: + *s++ = '>'; + break; + case SOAP_QT: + *s++ = '"'; + break; + case SOAP_AP: + *s++ = '\''; + break; + case '/': + if (n > 0) + { c = soap_getutf8(soap); + if (c == SOAP_GT) + n--; + soap_unget(soap, c); + } + *s++ = '/'; + break; + case '<': + if (flag) + *s++ = (soap_wchar)'<'; + else + { *s++ = (soap_wchar)'&'; + t = "lt;"; + } + break; + case '>': + if (flag) + *s++ = (soap_wchar)'>'; + else + { *s++ = (soap_wchar)'&'; + t = "gt;"; + } + break; + case '"': + if (flag) + *s++ = (soap_wchar)'"'; + else + { *s++ = (soap_wchar)'&'; + t = "quot;"; + } + break; + default: + if ((int)c == EOF) + goto end; + *s++ = (wchar_t)c & 0x7FFFFFFF; + } + l++; + if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); + soap->error = SOAP_LENGTH; + return NULL; + } + } + } +end: + soap_unget(soap, c); + *s = '\0'; + soap_size_block(soap, sizeof(wchar_t) * (i + 1)); + if ((soap->mode & SOAP_XML_STRICT) && l < minlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen)); + soap->error = SOAP_LENGTH; + return NULL; + } + s = (wchar_t*)soap_save_block(soap, NULL, 0); +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + soap->dom->wide = s; +#endif + return s; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_int2s(struct soap *soap, int n) +{ return soap_long2s(soap, (long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outint(struct soap *soap, const char *tag, int id, const int *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_long2s(soap, (long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2int(struct soap *soap, const char *s, int *p) +{ if (s) + { char *r; +#ifndef WITH_NOIO +#ifndef WITH_LEAN + soap_reset_errno; +#endif +#endif + *p = (int)soap_strtol(s, &r, 10); + if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r +#ifndef WITH_NOIO +#ifndef WITH_LEAN + || soap_errno == SOAP_ERANGE +#endif +#endif + ) + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int * +SOAP_FMAC2 +soap_inint(struct soap *soap, const char *tag, int *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":int") + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (int*)soap_id_enter(soap, soap->id, p, t, sizeof(int), 0, NULL, NULL, NULL); + if (*soap->href) + p = (int*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(int), 0, NULL); + else if (p) + { if (soap_s2int(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_long2s(struct soap *soap, long n) +{ sprintf(soap->tmpbuf, "%ld", n); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outlong(struct soap *soap, const char *tag, int id, const long *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_long2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2long(struct soap *soap, const char *s, long *p) +{ if (s) + { char *r; +#ifndef WITH_NOIO +#ifndef WITH_LEAN + soap_reset_errno; +#endif +#endif + *p = soap_strtol(s, &r, 10); + if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r +#ifndef WITH_NOIO +#ifndef WITH_LEAN + || soap_errno == SOAP_ERANGE +#endif +#endif + ) + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +long * +SOAP_FMAC2 +soap_inlong(struct soap *soap, const char *tag, long *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":int") + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (long*)soap_id_enter(soap, soap->id, p, t, sizeof(long), 0, NULL, NULL, NULL); + if (*soap->href) + p = (long*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(long), 0, NULL); + else if (p) + { if (soap_s2long(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_LONG642s(struct soap *soap, LONG64 n) +{ sprintf(soap->tmpbuf, SOAP_LONG_FORMAT, n); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outLONG64(struct soap *soap, const char *tag, int id, const LONG64 *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_LONG642s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2LONG64(struct soap *soap, const char *s, LONG64 *p) +{ if (s) + { +#ifdef HAVE_STRTOLL + char *r; +#ifndef WITH_NOIO +#ifndef WITH_LEAN + soap_reset_errno; +#endif +#endif + *p = strtoll(s, &r, 10); + if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r +#ifndef WITH_NOIO +#ifndef WITH_LEAN + || soap_errno == SOAP_ERANGE +#endif +#endif + ) +#else +# ifdef HAVE_SSCANF + if (sscanf(s, SOAP_LONG_FORMAT, p) != 1) +# endif +#endif + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +LONG64 * +SOAP_FMAC2 +soap_inLONG64(struct soap *soap, const char *tag, LONG64 *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":integer") + && soap_match_tag(soap, soap->type, ":positiveInteger") + && soap_match_tag(soap, soap->type, ":negativeInteger") + && soap_match_tag(soap, soap->type, ":nonPositiveInteger") + && soap_match_tag(soap, soap->type, ":nonNegativeInteger") + && soap_match_tag(soap, soap->type, ":long") + && soap_match_tag(soap, soap->type, ":int") + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (LONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(LONG64), 0, NULL, NULL, NULL); + if (*soap->href) + p = (LONG64*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(LONG64), 0, NULL); + else if (p) + { if (soap_s2LONG64(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_byte2s(struct soap *soap, char n) +{ return soap_long2s(soap, (long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outbyte(struct soap *soap, const char *tag, int id, const char *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_long2s(soap, (long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2byte(struct soap *soap, const char *s, char *p) +{ if (s) + { long n; + char *r; + n = soap_strtol(s, &r, 10); + if (s == r || *r || n < -128 || n > 127) + soap->error = SOAP_TYPE; + *p = (char)n; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_inbyte(struct soap *soap, const char *tag, char *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (char*)soap_id_enter(soap, soap->id, p, t, sizeof(char), 0, NULL, NULL, NULL); + if (*soap->href) + p = (char*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(char), 0, NULL); + else if (p) + { if (soap_s2byte(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_short2s(struct soap *soap, short n) +{ return soap_long2s(soap, (long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outshort(struct soap *soap, const char *tag, int id, const short *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_long2s(soap, (long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2short(struct soap *soap, const char *s, short *p) +{ if (s) + { long n; + char *r; + n = soap_strtol(s, &r, 10); + if (s == r || *r || n < -32768 || n > 32767) + soap->error = SOAP_TYPE; + *p = (short)n; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +short * +SOAP_FMAC2 +soap_inshort(struct soap *soap, const char *tag, short *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (short*)soap_id_enter(soap, soap->id, p, t, sizeof(short), 0, NULL, NULL, NULL); + if (*soap->href) + p = (short*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(short), 0, NULL); + else if (p) + { if (soap_s2short(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_float2s(struct soap *soap, float n) +{ const char *s; + if (soap_isnan((double)n)) + s = "NaN"; + else if (soap_ispinff(n)) + s = "INF"; + else if (soap_isninff(n)) + s = "-INF"; + else + { sprintf(soap->tmpbuf, soap->float_format, n); + s = soap->tmpbuf; + } + return s; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outfloat(struct soap *soap, const char *tag, int id, const float *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_float2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2float(struct soap *soap, const char *s, float *p) +{ if (s) + { if (!*s) + return soap->error = SOAP_TYPE; + if (!soap_tag_cmp(s, "INF")) + *p = FLT_PINFTY; + else if (!soap_tag_cmp(s, "+INF")) + *p = FLT_PINFTY; + else if (!soap_tag_cmp(s, "-INF")) + *p = FLT_NINFTY; + else if (!soap_tag_cmp(s, "NaN")) + *p = FLT_NAN; + else + { +/* On some systems, strtof appears to be broken or doesn't link: use with caution */ +#if defined(HAVE_STRTOF) + char *r; + *p = strtof((char*)s, &r); + if (*r) +#elif defined(HAVE_STRTOD) + char *r; + *p = (float)strtod(s, &r); + if (*r) +#endif +#ifdef HAVE_SSCANF + if (sscanf(s, "%g", p) != 1) + soap->error = SOAP_TYPE; +#else + soap->error = SOAP_TYPE; +#endif + } + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static int soap_isnumeric(struct soap *soap, const char *type) +{ if (soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":float") + && soap_match_tag(soap, soap->type, ":double") + && soap_match_tag(soap, soap->type, ":decimal") + && soap_match_tag(soap, soap->type, ":integer") + && soap_match_tag(soap, soap->type, ":positiveInteger") + && soap_match_tag(soap, soap->type, ":negativeInteger") + && soap_match_tag(soap, soap->type, ":nonPositiveInteger") + && soap_match_tag(soap, soap->type, ":nonNegativeInteger") + && soap_match_tag(soap, soap->type, ":long") + && soap_match_tag(soap, soap->type, ":int") + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte") + && soap_match_tag(soap, soap->type, ":unsignedLong") + && soap_match_tag(soap, soap->type, ":unsignedInt") + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return SOAP_ERR; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +float * +SOAP_FMAC2 +soap_infloat(struct soap *soap, const char *tag, float *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type != '\0' && soap_isnumeric(soap, type)) + return NULL; +#endif + p = (float*)soap_id_enter(soap, soap->id, p, t, sizeof(float), 0, NULL, NULL, NULL); + if (*soap->href) + p = (float*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(float), 0, NULL); + else if (p) + { if (soap_s2float(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_double2s(struct soap *soap, double n) +{ const char *s; + if (soap_isnan(n)) + s = "NaN"; + else if (soap_ispinfd(n)) + s = "INF"; + else if (soap_isninfd(n)) + s = "-INF"; + else + { sprintf(soap->tmpbuf, soap->double_format, n); + s = soap->tmpbuf; + } + return s; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outdouble(struct soap *soap, const char *tag, int id, const double *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_double2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2double(struct soap *soap, const char *s, double *p) +{ if (s) + { if (!*s) + return soap->error = SOAP_TYPE; + if (!soap_tag_cmp(s, "INF")) + *p = DBL_PINFTY; + else if (!soap_tag_cmp(s, "+INF")) + *p = DBL_PINFTY; + else if (!soap_tag_cmp(s, "-INF")) + *p = DBL_NINFTY; + else if (!soap_tag_cmp(s, "NaN")) + *p = DBL_NAN; + else + { +#ifdef HAVE_STRTOD + char *r; + *p = strtod(s, &r); + if (*r) +#endif +#ifdef HAVE_SSCANF + if (sscanf(s, "%lg", p) != 1) + soap->error = SOAP_TYPE; +#else + soap->error = SOAP_TYPE; +#endif + } + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +double * +SOAP_FMAC2 +soap_indouble(struct soap *soap, const char *tag, double *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type != '\0' && soap_isnumeric(soap, type)) + return NULL; +#endif + p = (double*)soap_id_enter(soap, soap->id, p, t, sizeof(double), 0, NULL, NULL, NULL); + if (*soap->href) + p = (double*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(double), 0, NULL); + else if (p) + { if (soap_s2double(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_unsignedByte2s(struct soap *soap, unsigned char n) +{ return soap_unsignedLong2s(soap, (unsigned long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outunsignedByte(struct soap *soap, const char *tag, int id, const unsigned char *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2unsignedByte(struct soap *soap, const char *s, unsigned char *p) +{ if (s) + { unsigned long n; + char *r; + n = soap_strtoul(s, &r, 10); + if (s == r || *r || n > 255) + soap->error = SOAP_TYPE; + *p = (unsigned char)n; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +unsigned char * +SOAP_FMAC2 +soap_inunsignedByte(struct soap *soap, const char *tag, unsigned char *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (unsigned char*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned char), 0, NULL, NULL, NULL); + if (*soap->href) + p = (unsigned char*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(unsigned char), 0, NULL); + else if (p) + { if (soap_s2unsignedByte(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_unsignedShort2s(struct soap *soap, unsigned short n) +{ return soap_unsignedLong2s(soap, (unsigned long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outunsignedShort(struct soap *soap, const char *tag, int id, const unsigned short *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2unsignedShort(struct soap *soap, const char *s, unsigned short *p) +{ if (s) + { unsigned long n; + char *r; + n = soap_strtoul(s, &r, 10); + if (s == r || *r || n > 65535) + soap->error = SOAP_TYPE; + *p = (unsigned short)n; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +unsigned short * +SOAP_FMAC2 +soap_inunsignedShort(struct soap *soap, const char *tag, unsigned short *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (unsigned short*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned short), 0, NULL, NULL, NULL); + if (*soap->href) + p = (unsigned short*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(unsigned short), 0, NULL); + else if (p) + { if (soap_s2unsignedShort(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_unsignedInt2s(struct soap *soap, unsigned int n) +{ return soap_unsignedLong2s(soap, (unsigned long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outunsignedInt(struct soap *soap, const char *tag, int id, const unsigned int *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2unsignedInt(struct soap *soap, const char *s, unsigned int *p) +{ if (s) + { char *r; +#ifndef WITH_NOIO +#ifndef WITH_LEAN + soap_reset_errno; +#endif +#endif + *p = (unsigned int)soap_strtoul(s, &r, 10); + if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r +#ifndef WITH_NOIO +#ifndef WITH_LEAN + || soap_errno == SOAP_ERANGE +#endif +#endif + ) + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +unsigned int * +SOAP_FMAC2 +soap_inunsignedInt(struct soap *soap, const char *tag, unsigned int *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":unsignedInt") + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (unsigned int*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned int), 0, NULL, NULL, NULL); + if (*soap->href) + p = (unsigned int*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(unsigned int), 0, NULL); + else if (p) + { if (soap_s2unsignedInt(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_unsignedLong2s(struct soap *soap, unsigned long n) +{ sprintf(soap->tmpbuf, "%lu", n); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outunsignedLong(struct soap *soap, const char *tag, int id, const unsigned long *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_unsignedLong2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2unsignedLong(struct soap *soap, const char *s, unsigned long *p) +{ if (s) + { char *r; +#ifndef WITH_NOIO +#ifndef WITH_LEAN + soap_reset_errno; +#endif +#endif + *p = soap_strtoul(s, &r, 10); + if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r +#ifndef WITH_NOIO +#ifndef WITH_LEAN + || soap_errno == SOAP_ERANGE +#endif +#endif + ) + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +unsigned long * +SOAP_FMAC2 +soap_inunsignedLong(struct soap *soap, const char *tag, unsigned long *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":unsignedInt") + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (unsigned long*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned long), 0, NULL, NULL, NULL); + if (*soap->href) + p = (unsigned long*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(unsigned long), 0, NULL); + else if (p) + { if (soap_s2unsignedLong(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_ULONG642s(struct soap *soap, ULONG64 n) +{ sprintf(soap->tmpbuf, SOAP_ULONG_FORMAT, n); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outULONG64(struct soap *soap, const char *tag, int id, const ULONG64 *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_ULONG642s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2ULONG64(struct soap *soap, const char *s, ULONG64 *p) +{ if (s) + { +#ifdef HAVE_STRTOULL + char *r; +#ifndef WITH_NOIO +#ifndef WITH_LEAN + soap_reset_errno; +#endif +#endif + *p = strtoull(s, &r, 10); + if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r +#ifndef WITH_NOIO +#ifndef WITH_LEAN + || soap_errno == SOAP_ERANGE +#endif +#endif + ) +#else +# ifdef HAVE_SSCANF + if (sscanf(s, SOAP_ULONG_FORMAT, p) != 1) +# endif +#endif + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +ULONG64 * +SOAP_FMAC2 +soap_inULONG64(struct soap *soap, const char *tag, ULONG64 *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":positiveInteger") + && soap_match_tag(soap, soap->type, ":nonNegativeInteger") + && soap_match_tag(soap, soap->type, ":unsignedLong") + && soap_match_tag(soap, soap->type, ":unsignedInt") + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } + p = (ULONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(ULONG64), 0, NULL, NULL, NULL); + if (*soap->href) + p = (ULONG64*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(ULONG64), 0, NULL); + else if (p) + { if (soap_s2ULONG64(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2string(struct soap *soap, const char *s, char **t) +{ *t = NULL; + if (s && !(*t = soap_strdup(soap, s))) + return soap->error = SOAP_EOM; + if (!(soap->mode & (SOAP_ENC_LATIN | SOAP_C_UTFSTRING))) + { /* TODO: consider truncating UTF8 to ASCII for XML attribute strings? */ + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2QName(struct soap *soap, const char *s, char **t) +{ if (s) + { struct soap_nlist *np; + const char *p; + if (!strncmp(s, "xml:", 4)) + { *t = soap_strdup(soap, s); + return SOAP_OK; + } + np = soap->nlist; + p = strchr(s, ':'); + if (p) + { register int n = p - s; + while (np && (strncmp(np->id, s, n) || np->id[n])) + np = np->next; + p++; + } + else + { while (np && *np->id) + np = np->next; + p = s; + } + if (np) + { if (np->index >= 0 && soap->local_namespaces) + { register const char *q = soap->local_namespaces[np->index].id; + if (q) + { if ((*t = (char*)soap_malloc(soap, strlen(p) + strlen(q) + 2))) + sprintf(*t, "%s:%s", q, p); + return SOAP_OK; + } + } + if (np->ns) + { if ((*t = (char*)soap_malloc(soap, strlen(p) + strlen(np->ns) + 4))) + sprintf(*t, "\"%s\":%s", np->ns, p); + return SOAP_OK; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Namespace prefix of '%s' not defined (index=%d, URI=%s)\n", s, np->index, np->ns?np->ns:"")); + return soap->error = SOAP_NAMESPACE; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Namespace prefix of '%s' not defined, assuming empty namespace\n", s)); + if ((*t = (char*)soap_malloc(soap, strlen(p) + 4))) + sprintf(*t, "\"\":%s", p); + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_QName2s(struct soap *soap, const char *s) +{ struct Namespace *p; + char *t; + int n; + if (!s || *s != '"') + { +#ifndef WITH_LEAN + if (s && (soap->mode & SOAP_XML_CANONICAL)) + { t = (char*)strchr(s, ':'); + if (t) + soap_utilize_ns(soap, s, t - s); + } +#endif + return s; + } + s++; + if ((p = soap->local_namespaces)) + { for (; p->id; p++) + { if (p->ns) + if (!soap_tag_cmp(s, p->ns)) + break; + if (p->in) + if (!soap_tag_cmp(s, p->in)) + break; + } + if (p && p->id) + { s = strchr(s, '"'); + if (s) + { t = (char*)soap_malloc(soap, strlen(p->id) + strlen(s)); + strcpy(t, p->id); + strcat(t, s + 1); + return t; + } + } + } + t = (char*)strchr(s, '"'); + if (t) + n = t - s; + else + n = 0; + t = soap_strdup(soap, s); + t[n] = '\0'; + sprintf(soap->tmpbuf, "xmlns:_%d", soap->idnum++); + soap_set_attr(soap, soap->tmpbuf, t); + s = strchr(s, '"'); + if (s) + { t = (char*)soap_malloc(soap, strlen(soap->tmpbuf) + strlen(s) - 6); + strcpy(t, soap->tmpbuf + 6); + strcat(t, s + 1); + } + return t; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2wchar(struct soap *soap, const char *s, wchar_t **t) +{ wchar_t *r; + if (!s) + *t = NULL; + else + { *t = r = (wchar_t*)soap_malloc(soap, sizeof(wchar_t) * (strlen(s) + 1)); + if (!r) + return soap->error; + if (soap->mode & SOAP_ENC_LATIN) + { while (*s) + *r++ = (wchar_t)*s++; + } + else + { /* Convert UTF8 to wchar */ + while (*s) + { register soap_wchar c, c1, c2, c3, c4; + c = *s++; + if (c < 0x80) + *r++ = (wchar_t)c; + else + { c1 = (soap_wchar)*s++ & 0x3F; + if (c < 0xE0) + *r++ = (wchar_t)(((soap_wchar)(c & 0x1F) << 6) | c1); + else + { c2 = (soap_wchar)*s++ & 0x3F; + if (c < 0xF0) + *r++ = (wchar_t)(((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2); + else + { c3 = (soap_wchar)*s++ & 0x3F; + if (c < 0xF8) + *r++ = (wchar_t)(((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3); + else + { c4 = (soap_wchar)*s++ & 0x3F; + if (c < 0xFC) + *r++ = (wchar_t)(((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4); + else + *r++ = (wchar_t)(((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(*s++ & 0x3F)); + } + } + } + } + } + } + *r = L'\0'; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_wchar2s(struct soap *soap, const wchar_t *s) +{ register soap_wchar c; + register char *r, *t; + const wchar_t *q = s; + size_t n = 0; + while ((c = *q++)) + { if (c > 0 && c < 0x80) + n++; + else + n += 6; + } + r = t = (char*)soap_malloc(soap, n + 1); + if (r) + { /* Convert wchar to UTF8 */ + while ((c = *s++)) + { if (c > 0 && c < 0x80) + *t++ = (char)c; + else + { if (c < 0x0800) + *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); + else + { if (c < 0x010000) + *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + else + { if (c < 0x200000) + *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + else + { if (c < 0x04000000) + *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + else + { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + } + *t++ = (char)(0x80 | (c & 0x3F)); + } + } + *t = '\0'; + } + return r; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outstring(struct soap *soap, const char *tag, int id, char *const*p, const char *type, int n) +{ id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n); + if (id < 0 + || soap_element_begin_out(soap, tag, id, type) + || soap_string_out(soap, *p, 0) + || soap_element_end_out(soap, tag)) + return soap->error; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char ** +SOAP_FMAC2 +soap_instring(struct soap *soap, const char *tag, char **p, const char *type, int t, int flag, long minlen, long maxlen) +{ if (soap_element_begin_in(soap, tag, 1)) + { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG) + return NULL; + soap->error = SOAP_OK; + } + if (!p) + if (!(p = (char**)soap_malloc(soap, sizeof(char*)))) + return NULL; + if (soap->body) + { *p = soap_string_in(soap, flag, minlen, maxlen); + if (!*p || !(char*)soap_id_enter(soap, soap->id, *p, t, sizeof(char*), 0, NULL, NULL, NULL)) + return NULL; + } + else if (soap->null) + *p = NULL; + else + *p = (char*)SOAP_STR_EOS; + if (*soap->href) + p = (char**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(char**), 0); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outwstring(struct soap *soap, const char *tag, int id, wchar_t *const*p, const char *type, int n) +{ id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n); + if (id < 0 + || soap_element_begin_out(soap, tag, id, type) + || soap_wstring_out(soap, *p, 0) + || soap_element_end_out(soap, tag)) + return soap->error; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +wchar_t ** +SOAP_FMAC2 +soap_inwstring(struct soap *soap, const char *tag, wchar_t **p, const char *type, int t, long minlen, long maxlen) +{ if (soap_element_begin_in(soap, tag, 1)) + { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG) + return NULL; + soap->error = SOAP_OK; + } + if (!p) + if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*)))) + return NULL; + if (soap->body) + { *p = soap_wstring_in(soap, 1, minlen, maxlen); + if (!*p || !(wchar_t*)soap_id_enter(soap, soap->id, *p, t, sizeof(wchar_t*), 0, NULL, NULL, NULL)) + return NULL; + } + else if (soap->null) + *p = NULL; + else + *p = (wchar_t*)SOAP_STR_EOS; + if (*soap->href) + p = (wchar_t**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(wchar_t**), 0); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static time_t +soap_timegm(struct tm *T) +{ +#if defined(HAVE_TIMEGM) + return timegm(T); +#else + time_t t, g, z; +#ifdef HAVE_GMTIME_R + struct tm tm, *tmp = &tm; +#else + struct tm *tmp; +#endif + t = mktime(T); + if (t == -1) + return -1; +#ifdef HAVE_GMTIME_R + gmtime_r(&t, tmp); +#else + tmp = gmtime(&t); +#endif + tmp->tm_isdst = 0; + g = mktime(tmp); + if (g == -1) + return -1; + z = g - t; + return t - z; +#endif +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_dateTime2s(struct soap *soap, time_t n) +{ struct tm T, *pT = &T; +#if defined(HAVE_GMTIME_R) + if (gmtime_r(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); + /* The following defines were added for VxWorks*/ +#elif defined(HAVE_PGMTIME_R) + if (gmtime_r(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); +#elif defined(HAVE_PGMTIME) + if (gmtime(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); +#elif defined(HAVE_GMTIME) + if ((pT = gmtime(&n))) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); +#elif defined(HAVE_GETTIMEOFDAY) + struct timezone tz; + memset((void*)&tz, 0, sizeof(tz)); +# if defined(HAVE_LOCALTIME_R) + if (localtime_r(&n, pT)) + { struct timeval tv; + gettimeofday(&tv, &tz); + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60); + } +# else + if ((pT = localtime(&n))) + { struct timeval tv; + gettimeofday(&tv, &tz); + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60); + } +#endif +#elif defined(HAVE_FTIME) + struct timeb t; + memset((void*)&t, 0, sizeof(t)); +# if defined(HAVE_LOCALTIME_R) + if (localtime_r(&n, pT)) + { ftime(&t); + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60); + } + /* The following defines were added for VxWorks*/ +# elif defined(HAVE_PLOCALTIME_R) + if (localtime_r(&n, pT)) + { strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf+strlen(soap->tmpbuf), "%+03d:%02d", t.timezone/60, abs(t.timezone)%60); + } +# else + if ((pT = localtime(&n))) + { ftime(&t); + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60); + } +# endif +#elif defined(HAVE_LOCALTIME_R) + if (localtime_r(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + /* The following defines were added for VxWorks*/ +#elif defined(HAVE_PLOCALTIME_R) + if (localtime_r(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); +#else + if ((pT = localtime(&n))) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); +#endif + else + strcpy(soap->tmpbuf, "1969-12-31T23:59:59Z"); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outdateTime(struct soap *soap, const char *tag, int id, const time_t *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_dateTime2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2dateTime(struct soap *soap, const char *s, time_t *p) +{ if (s) + { struct tm T; + char zone[16]; + const char *t; + memset((void*)&T, 0, sizeof(T)); + zone[sizeof(zone)-1] = '\0'; + if (strchr(s, '-')) + t = "%d-%d-%dT%d:%d:%d%15s"; + else if (strchr(s, ':')) + t = "%4d%2d%2dT%d:%d:%d%15s"; + else /* parse non-XSD-standard alternative ISO 8601 format */ + t = "%4d%2d%2dT%2d%2d%2d%15s"; + sscanf(s, t, &T.tm_year, &T.tm_mon, &T.tm_mday, &T.tm_hour, &T.tm_min, &T.tm_sec, zone); + if (T.tm_year == 1) + T.tm_year = 70; + else + T.tm_year -= 1900; + T.tm_mon--; + if (*zone) + { if (*zone == '.') + { for (s = zone + 1; *s; s++) + if (*s < '0' || *s > '9') + break; + } + else + s = zone; + if (*s == '+' || *s == '-') + { int h = 0, m = 0; + if (s[3] == ':') + { sscanf(s, "%d:%d", &h, &m); + if (h < 0) + m = -m; + } + else + { m = (int)atol(s); + h = m / 100; + m = m % 100; + } + T.tm_hour -= h; + T.tm_min -= m; + } + T.tm_isdst = 0; + *p = soap_timegm(&T); + } + else + { T.tm_isdst = -1; + *p = mktime(&T); /* no time zone: suppose it is localtime? */ + } + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +time_t * +SOAP_FMAC2 +soap_indateTime(struct soap *soap, const char *tag, time_t *p, const char * type, int t) +{ if (soap_element_begin_in(soap, tag, 0)) + return NULL; + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":dateTime")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } + p = (time_t*)soap_id_enter(soap, soap->id, p, t, sizeof(time_t), 0, NULL, NULL, NULL); + if (*soap->href) + p = (time_t*)soap_id_forward(soap, soap->href, p, t, 0, sizeof(time_t), 0, NULL); + else if (p) + { if (soap_s2dateTime(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outliteral(struct soap *soap, const char *tag, char *const*p) +{ int i; + const char *t = NULL; + if (tag && *tag != '-') + { if (soap->local_namespaces && (t = strchr(tag, ':'))) + { strncpy(soap->tmpbuf, tag, t-tag); + soap->tmpbuf[t-tag] = '\0'; + for (i = 0; soap->local_namespaces[i].id; i++) + if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id)) + break; + t++; + sprintf(soap->tmpbuf, "<%s xmlns=\"%s\">", t, soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS); + } + else + { t = tag; + sprintf(soap->tmpbuf, "<%s>", tag); + } + if (soap_send(soap, soap->tmpbuf)) + return soap->error; + } + if (p && *p) + { if (soap_send(soap, *p)) + return soap->error; + } + if (t) + { sprintf(soap->tmpbuf, "", t); + return soap_send(soap, soap->tmpbuf); + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char ** +SOAP_FMAC2 +soap_inliteral(struct soap *soap, const char *tag, char **p) +{ if (soap_element_begin_in(soap, tag, 1)) + { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT) + return NULL; + soap->error = SOAP_OK; + } + if (!p) + if (!(p = (char**)soap_malloc(soap, sizeof(char*)))) + return NULL; + if (soap->body) + *p = soap_string_in(soap, 0, -1, -1); + else if (soap->null) + *p = NULL; + else + *p = (char*)SOAP_STR_EOS; + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outwliteral(struct soap *soap, const char *tag, wchar_t *const*p) +{ int i; + const char *t = NULL; + wchar_t c; + const wchar_t *s; + if (tag && *tag != '-') + { if (soap->local_namespaces && (t = strchr(tag, ':'))) + { strncpy(soap->tmpbuf, tag, t-tag); + soap->tmpbuf[t-tag] = '\0'; + for (i = 0; soap->local_namespaces[i].id; i++) + if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id)) + break; + t++; + sprintf(soap->tmpbuf, "<%s xmlns=\"%s\">", t, soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS); + } + else + { t = tag; + sprintf(soap->tmpbuf, "<%s>", tag); + } + if (soap_send(soap, soap->tmpbuf)) + return soap->error; + } + if (p) + { s = *p; + while ((c = *s++)) + if (soap_pututf8(soap, (unsigned char)c)) + return soap->error; + } + if (t) + { sprintf(soap->tmpbuf, "", t); + return soap_send(soap, soap->tmpbuf); + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +wchar_t ** +SOAP_FMAC2 +soap_inwliteral(struct soap *soap, const char *tag, wchar_t **p) +{ if (soap_element_begin_in(soap, tag, 1)) + { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT) + return NULL; + soap->error = SOAP_OK; + } + if (!p) + if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*)))) + return NULL; + if (soap->body) + *p = soap_wstring_in(soap, 0, -1, -1); + else if (soap->null) + *p = NULL; + else + *p = (wchar_t*)SOAP_STR_EOS; + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char * +SOAP_FMAC2 +soap_token(struct soap *soap) +{ register size_t i; + register soap_wchar c = 0; + register char *s = soap->tmpbuf; + if (!soap->body) + return SOAP_STR_EOS; + do c = soap_get(soap); + while (soap_blank(c)); + for (i = 0; i < sizeof(soap->tmpbuf) - 1; i++) + { if (c == SOAP_TT || (int)c == EOF || soap_blank(c)) + break; + *s++ = (char)c; + c = soap_get(soap); + } + if ((int)c == EOF || c == SOAP_TT) + soap_unget(soap, c); + *s = '\0'; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element content value='%s'\n", soap->tmpbuf)); + return soap->tmpbuf; /* return non-null pointer */ +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char * +SOAP_FMAC2 +soap_value(struct soap *soap) +{ register size_t i; + register soap_wchar c = 0; + register char *s = soap->tmpbuf; + if (!soap->body) + return SOAP_STR_EOS; + do c = soap_get(soap); + while (soap_blank(c)); + for (i = 0; i < sizeof(soap->tmpbuf) - 1; i++) + { if (c == SOAP_TT || (int)c == EOF) + break; + *s++ = (char)c; + c = soap_get(soap); + } + for (s--; i > 0; i--, s--) + if (!soap_blank(*s)) + break; + s[1] = '\0'; + if ((int)c == EOF || c == SOAP_TT) + soap_unget(soap, c); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element content value='%s'\n", soap->tmpbuf)); +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + soap->dom->data = soap_strdup(soap, soap->tmpbuf); +#endif + return soap->tmpbuf; /* return non-null pointer */ +} +#endif + +/******************************************************************************/ +#if !defined(WITH_LEANER) || !defined(WITH_NOHTTP) +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getline(struct soap *soap, char *s, int len) +{ int i = len; + soap_wchar c = 0; + for (;;) + { while (--i > 0) + { c = soap_getchar(soap); + if (c == '\r' || c == '\n') + break; + if ((int)c == EOF) + return soap->error = SOAP_EOF; + *s++ = (char)c; + } + if (c != '\n') + c = soap_getchar(soap); /* got \r, now get \n */ + if (c == '\n') + { *s = '\0'; + if (i+1 == len) /* empty line: end of HTTP/MIME header */ + break; + c = soap_unget(soap, soap_getchar(soap)); + if (c != ' ' && c != '\t') /* HTTP line continuation? */ + break; + } + else if ((int)c == EOF) + return soap->error = SOAP_EOF; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static size_t +soap_count_attachments(struct soap *soap) +{ +#ifndef WITH_LEANER + register struct soap_multipart *content; + register size_t count = soap->count; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the message size with attachments, current count=%lu\n", (unsigned long)count)); + if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of DIME attachments\n")); + for (content = soap->dime.first; content; content = content->next) + { count += 12 + ((content->size+3)&(~3)); + if (content->id) + count += ((strlen(content->id)+3)&(~3)); + if (content->type) + count += ((strlen(content->type)+3)&(~3)); + if (content->options) + count += ((((unsigned char)content->options[2] << 8) | ((unsigned char)content->options[3]))+7)&(~3); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of DIME attachment content is %lu bytes\n", (unsigned long)content->size)); + } + } + if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary) + { register size_t n = strlen(soap->mime.boundary); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of MIME attachments\n")); + for (content = soap->mime.first; content; content = content->next) + { register const char *s; + /* count \r\n--boundary\r\n */ + count += 6 + n; + /* count Content-Type: ...\r\n */ + if (content->type) + count += 16 + strlen(content->type); + /* count Content-Transfer-Encoding: ...\r\n */ + s = soap_str_code(mime_codes, content->encoding); + if (s) + count += 29 + strlen(s); + /* count Content-ID: ...\r\n */ + if (content->id) + count += 14 + strlen(content->id); + /* count Content-Location: ...\r\n */ + if (content->location) + count += 20 + strlen(content->location); + /* count Content-Description: ...\r\n */ + if (content->description) + count += 23 + strlen(content->location); + /* count \r\n...content */ + count += 2 + content->size; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of MIME attachment content is %lu bytes\n", (unsigned long)content->size)); + } + /* count \r\n--boundary-- */ + count += 6 + n; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New count is %lu bytes\n", (unsigned long)count)); + return count; +#else + return soap->count; +#endif +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static int +soap_putdimefield(struct soap *soap, const char *s, size_t n) +{ if (soap_send_raw(soap, s, n)) + return soap->error; + return soap_send_raw(soap, SOAP_STR_PADDING, -(long)n&3); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_dime_option(struct soap *soap, unsigned short optype, const char *option) +{ size_t n; + char *s = NULL; + if (option) + { n = strlen(option); + s = (char*)soap_malloc(soap, n + 5); + if (s) + { s[0] = optype >> 8; + s[1] = optype & 0xFF; + s[2] = n >> 8; + s[3] = n & 0xFF; + strcpy(s + 4, option); + } + } + return s; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putdimehdr(struct soap *soap) +{ unsigned char tmp[12]; + size_t optlen = 0, idlen = 0, typelen = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Put DIME header id='%s'\n", soap->dime.id?soap->dime.id:"")); + if (soap->dime.options) + optlen = (((unsigned char)soap->dime.options[2] << 8) | ((unsigned char)soap->dime.options[3])) + 4; + if (soap->dime.id) + idlen = strlen(soap->dime.id); + if (soap->dime.type) + typelen = strlen(soap->dime.type); + tmp[0] = SOAP_DIME_VERSION | (soap->dime.flags & 0x7); + tmp[1] = soap->dime.flags & 0xF0; + tmp[2] = optlen >> 8; + tmp[3] = optlen & 0xFF; + tmp[4] = idlen >> 8; + tmp[5] = idlen & 0xFF; + tmp[6] = typelen >> 8; + tmp[7] = typelen & 0xFF; + tmp[8] = soap->dime.size >> 24; + tmp[9] = (soap->dime.size >> 16) & 0xFF; + tmp[10] = (soap->dime.size >> 8) & 0xFF; + tmp[11] = soap->dime.size & 0xFF; + if (soap_send_raw(soap, (char*)tmp, 12) + || soap_putdimefield(soap, soap->dime.options, optlen) + || soap_putdimefield(soap, soap->dime.id, idlen) + || soap_putdimefield(soap, soap->dime.type, typelen)) + return soap->error; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putdime(struct soap *soap) +{ struct soap_multipart *content; + if (!(soap->mode & SOAP_ENC_DIME)) + return SOAP_OK; + for (content = soap->dime.first; content; content = content->next) + { void *handle; + soap->dime.size = content->size; + soap->dime.id = content->id; + soap->dime.type = content->type; + soap->dime.options = content->options; + soap->dime.flags = SOAP_DIME_VERSION | SOAP_DIME_MEDIA; + if (soap->fdimereadopen && ((handle = soap->fdimereadopen(soap, (void*)content->ptr, content->id, content->type, content->options)) || soap->error)) + { size_t size = content->size; + if (!handle) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadopen failed\n")); + return soap->error; + } + if (!content->size && ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE)) + { size_t chunksize = sizeof(soap->tmpbuf); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming DIME\n")); + do + { size = soap->fdimeread(soap, handle, soap->tmpbuf, chunksize); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread returned %lu bytes\n", (unsigned long)size)); + if (size < chunksize) + { soap->dime.flags &= ~SOAP_DIME_CF; + if (!content->next) + soap->dime.flags |= SOAP_DIME_ME; + } + else + soap->dime.flags |= SOAP_DIME_CF; + soap->dime.size = size; + if (soap_putdimehdr(soap) + || soap_putdimefield(soap, soap->tmpbuf, size)) + break; + if (soap->dime.id) + { soap->dime.flags &= ~(SOAP_DIME_MB | SOAP_DIME_MEDIA); + soap->dime.id = NULL; + soap->dime.type = NULL; + soap->dime.options = NULL; + } + } while (size >= chunksize); + } + else + { if (!content->next) + soap->dime.flags |= SOAP_DIME_ME; + if (soap_putdimehdr(soap)) + return soap->error; + do + { size_t bufsize; + if (size < sizeof(soap->tmpbuf)) + bufsize = size; + else + bufsize = sizeof(soap->tmpbuf); + if (!(bufsize = soap->fdimeread(soap, handle, soap->tmpbuf, bufsize))) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)soap->dime.size)); + soap->error = SOAP_EOF; + break; + } + if (soap_send_raw(soap, soap->tmpbuf, bufsize)) + break; + size -= bufsize; + } while (size); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n")); + soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3); + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n")); + if (soap->fdimereadclose) + soap->fdimereadclose(soap, handle); + } + else + { if (!content->next) + soap->dime.flags |= SOAP_DIME_ME; + if (soap_putdimehdr(soap) + || soap_putdimefield(soap, (char*)content->ptr, content->size)) + return soap->error; + } + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static char * +soap_getdimefield(struct soap *soap, size_t n) +{ register soap_wchar c; + register int i; + register char *s; + char *p = NULL; + if (n) + { p = (char*)soap_malloc(soap, n + 1); + if (p) + { s = p; + for (i = n; i > 0; i--) + { if ((int)(c = soap_get1(soap)) == EOF) + { soap->error = SOAP_EOF; + return NULL; + } + *s++ = (char)c; + } + *s = '\0'; + if ((soap->error = soap_move(soap, -(long)n&3))) + return NULL; + } + else + soap->error = SOAP_EOM; + } + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getdimehdr(struct soap *soap) +{ register soap_wchar c; + register char *s; + register int i; + unsigned char tmp[12]; + size_t optlen, idlen, typelen; + if (!(soap->mode & SOAP_ENC_DIME)) + return soap->error = SOAP_DIME_END; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME header\n")); + if (soap->dime.buflen || soap->dime.chunksize) + { if (soap_move(soap, (long)(soap->dime.size - soap_tell(soap)))) + return soap->error = SOAP_EOF; + soap_unget(soap, soap_getchar(soap)); /* skip padding and get hdr */ + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... From chunked\n")); + return SOAP_OK; + } + s = (char*)tmp; + for (i = 12; i > 0; i--) + { if ((int)(c = soap_getchar(soap)) == EOF) + return soap->error = SOAP_EOF; + *s++ = (char)c; + } + if ((tmp[0] & 0xF8) != SOAP_DIME_VERSION) + return soap->error = SOAP_DIME_MISMATCH; + soap->dime.flags = (tmp[0] & 0x7) | (tmp[1] & 0xF0); + optlen = (tmp[2] << 8) | tmp[3]; + idlen = (tmp[4] << 8) | tmp[5]; + typelen = (tmp[6] << 8) | tmp[7]; + soap->dime.size = (tmp[8] << 24) | (tmp[9] << 16) | (tmp[10] << 8) | tmp[11]; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME size=%lu flags=0x%X\n", (unsigned long)soap->dime.size, soap->dime.flags)); + if (!(soap->dime.options = soap_getdimefield(soap, optlen)) && soap->error) + return soap->error; + if (!(soap->dime.id = soap_getdimefield(soap, idlen)) && soap->error) + return soap->error; + if (!(soap->dime.type = soap_getdimefield(soap, typelen)) && soap->error) + return soap->error; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME id=%s, type=%s, options=%s\n", soap->dime.id?soap->dime.id:"", soap->dime.type?soap->dime.type:"", soap->dime.options?soap->dime.options+4:"")); + if (soap->dime.flags & SOAP_DIME_ME) + soap->mode &= ~SOAP_ENC_DIME; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getdime(struct soap *soap) +{ while (soap->dime.flags & SOAP_DIME_CF) + { if (soap_getdimehdr(soap)) + return soap->error; + if (soap_move(soap, soap->dime.size)) + return soap->error = SOAP_EOF; + } + if (soap_move(soap, ((soap->dime.size+3)&(~3))-soap_tell(soap))) + return soap->error = SOAP_EOF; + for (;;) + { register struct soap_multipart *content; + if (soap_getdimehdr(soap)) + break; + if (soap->fdimewriteopen && ((soap->dime.ptr = (char*)soap->fdimewriteopen(soap, soap->dime.id, soap->dime.type, soap->dime.options)) || soap->error)) + { const char *id, *type, *options; + size_t size, n; + if (!soap->dime.ptr) + return soap->error; + id = soap->dime.id; + type = soap->dime.type; + options = soap->dime.options; + for (;;) + { size = soap->dime.size; + for (;;) + { n = soap->buflen - soap->bufidx; + if (size < n) + n = size; + if ((soap->error = soap->fdimewrite(soap, (void*)soap->dime.ptr, soap->buf + soap->bufidx, n))) + break; + size -= n; + if (!size) + { soap->bufidx += n; + break; + } + if (soap_recv(soap)) + { soap->error = SOAP_EOF; + goto end; + } + } + if (soap_move(soap, -(long)soap->dime.size&3)) + { soap->error = SOAP_EOF; + break; + } + if (!(soap->dime.flags & SOAP_DIME_CF)) + break; + if (soap_getdimehdr(soap)) + break; + } +end: + if (soap->fdimewriteclose) + soap->fdimewriteclose(soap, (void*)soap->dime.ptr); + soap->dime.size = 0; + soap->dime.id = id; + soap->dime.type = type; + soap->dime.options = options; + } + else if (soap->dime.flags & SOAP_DIME_CF) + { const char *id, *type, *options; + register soap_wchar c; + register char *s; + register int i; + id = soap->dime.id; + type = soap->dime.type; + options = soap->dime.options; + if (soap_new_block(soap)) + return SOAP_EOM; + for (;;) + { s = (char*)soap_push_block(soap, soap->dime.size); + if (!s) + return soap->error = SOAP_EOM; + for (i = soap->dime.size; i > 0; i--) + { if ((int)(c = soap_get1(soap)) == EOF) + return soap->error = SOAP_EOF; + *s++ = (char)c; + } + if (soap_move(soap, -(long)soap->dime.size&3)) + return soap->error = SOAP_EOF; + if (!(soap->dime.flags & SOAP_DIME_CF)) + break; + if (soap_getdimehdr(soap)) + return soap->error; + } + soap->dime.size = soap->blist->size++; /* allocate one more for '\0' */ + if (!(soap->dime.ptr = soap_save_block(soap, NULL, 0))) + return soap->error; + soap->dime.ptr[soap->dime.size] = '\0'; /* force 0-terminated */ + soap->dime.id = id; + soap->dime.type = type; + soap->dime.options = options; + } + else + soap->dime.ptr = soap_getdimefield(soap, soap->dime.size); + content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, soap->dime.ptr, soap->dime.size); + if (!content) + return soap->error = SOAP_EOM; + content->id = soap->dime.id; + content->type = soap->dime.type; + content->options = soap->dime.options; + soap_resolve_attachment(soap, content); + if (soap->error) + return soap->error; + } + if (soap->error != SOAP_DIME_END) + return soap->error; + return soap->error = SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getmimehdr(struct soap *soap) +{ struct soap_multipart *content; + do + { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) + return soap->error; + } + while (!*soap->msgbuf); + if (soap->msgbuf[0] == '-' && soap->msgbuf[1] == '-') + { char *s = soap->msgbuf + strlen(soap->msgbuf) - 1; + /* remove white space */ + while (soap_blank(*s)) + s--; + s[1] = '\0'; + if (soap->mime.boundary) + { if (strcmp(soap->msgbuf + 2, soap->mime.boundary)) + return soap->error = SOAP_MIME_ERROR; + } + else + soap->mime.boundary = soap_strdup(soap, soap->msgbuf + 2); + if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) + return soap->error; + } + if (soap_set_mime_attachment(soap, NULL, 0, SOAP_MIME_NONE, NULL, NULL, NULL, NULL)) + return soap->error = SOAP_EOM; + content = soap->mime.last; + for (;;) + { register char *key = soap->msgbuf; + register char *val; + if (!*key) + break; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "MIME header: %s\n", key)); + val = strchr(soap->msgbuf, ':'); + if (val) + { *val = '\0'; + do val++; + while (*val && *val <= 32); + if (!soap_tag_cmp(key, "Content-ID")) + content->id = soap_strdup(soap, val); + else if (!soap_tag_cmp(key, "Content-Location")) + content->location = soap_strdup(soap, val); + else if (!soap_tag_cmp(key, "Content-Disposition")) + content->id = soap_strdup(soap, soap_get_header_attribute(soap, val, "name")); + else if (!soap_tag_cmp(key, "Content-Type")) + content->type = soap_strdup(soap, val); + else if (!soap_tag_cmp(key, "Content-Description")) + content->description = soap_strdup(soap, val); + else if (!soap_tag_cmp(key, "Content-Transfer-Encoding")) + content->encoding = (enum soap_mime_encoding)soap_int_code(mime_codes, val, (long)SOAP_MIME_NONE); + } + if (soap_getline(soap, key, sizeof(soap->msgbuf))) + return soap->error; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getmime(struct soap *soap) +{ register soap_wchar c = 0; + if (!soap->mime.last) + return SOAP_OK; + for (;;) + { register size_t i, m = 0; + register char *s, *t = NULL; + struct soap_multipart *content = soap->mime.last; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Parsing MIME content id=%s type=%s\n", content->id?content->id:"", content->type?content->type:"")); + if (soap_new_block(soap)) + return soap->error = SOAP_EOM; + for (;;) + { register short flag = 0; + if (!(s = (char*)soap_push_block(soap, SOAP_BLKLEN))) + return soap->error = SOAP_EOM; + for (i = 0; i < SOAP_BLKLEN; i++) + { if (m > 0) + { *s++ = *t++; + m--; + } + else + { if (!flag) + { c = soap_get1(soap); + if ((int)c == EOF) + return soap->error = SOAP_EOF; + } + if (flag || c == '\r') + { t = soap->tmpbuf; + memset(t, 0, sizeof(soap->tmpbuf)); + strcpy(t, "\n--"); + if (soap->mime.boundary) + strncat(t, soap->mime.boundary, sizeof(soap->tmpbuf)-4); + do c = soap_getchar(soap); + while (c == *t++); + if ((int)c == EOF) + return soap->error = SOAP_EOF; + if (!*--t) + goto end; + *t = (char)c; + flag = (c == '\r'); + m = t - soap->tmpbuf + 1 - flag; + t = soap->tmpbuf; + c = '\r'; + } + *s++ = (char)c; + } + } + } +end: + *s = '\0'; /* force 0-terminated */ + content->size = soap_size_block(soap, i+1)-1; + content->ptr = soap_save_block(soap, NULL, 0); + soap_resolve_attachment(soap, content); + if (c == '-' && soap_getchar(soap) == '-') + break; + while (c != '\r' && (int)c != EOF && soap_blank(c)) + c = soap_getchar(soap); + if (c != '\r' || soap_getchar(soap) != '\n') + return soap->error = SOAP_MIME_ERROR; + if (soap_getmimehdr(soap)) + return soap->error; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static int +soap_match_cid(struct soap *soap, const char *s, const char *t) +{ register size_t n; + if (!s) + return 1; + if (!strcmp(s, t)) + return 0; + if (!strncmp(s, "cid:", 4)) + s += 4; + n = strlen(t); + if (*t == '<') + { t++; + n -= 2; + } + if (!strncmp(s, t, n) && !s[n]) + return 0; + soap_decode(soap->tmpbuf, sizeof(soap->tmpbuf), s, SOAP_STR_EOS); + if (!strncmp(soap->tmpbuf, t, n) && !soap->tmpbuf[n]) + return 0; + return 1; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static void +soap_resolve_attachment(struct soap *soap, struct soap_multipart *content) +{ if (content->id) + { register struct soap_xlist **xp = &soap->xlist; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving attachment data for id=%s\n", content->id)); + while (*xp) + { register struct soap_xlist *xq = *xp; + if (!soap_match_cid(soap, xq->id, content->id)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Found matching attachment %s for content id=%s\n", xq->id, content->id)); + *xp = xq->next; + *xq->ptr = (unsigned char*)content->ptr; + *xq->size = (int)content->size; + *xq->type = (char*)content->type; + if (content->options) + *xq->options = (char*)content->options; + else + *xq->options = (char*)content->description; + SOAP_FREE(soap, xq); + } + else + xp = &(*xp)->next; + } + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putmimehdr(struct soap *soap, struct soap_multipart *content) +{ const char *s; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "MIME attachment type=%s\n", content->type?content->type:"")); + if (soap_send3(soap, "\r\n--", soap->mime.boundary, "\r\n")) + return soap->error; + if (content->type && soap_send3(soap, "Content-Type: ", content->type, "\r\n")) + return soap->error; + s = soap_str_code(mime_codes, content->encoding); + if (s && soap_send3(soap, "Content-Transfer-Encoding: ", s, "\r\n")) + return soap->error; + if (content->id && soap_send3(soap, "Content-ID: ", content->id, "\r\n")) + return soap->error; + if (content->location && soap_send3(soap, "Content-Location: ", content->location, "\r\n")) + return soap->error; + if (content->description && soap_send3(soap, "Content-Description: ", content->description, "\r\n")) + return soap->error; + return soap_send_raw(soap, "\r\n", 2); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putmime(struct soap *soap) +{ struct soap_multipart *content; + if (!(soap->mode & SOAP_ENC_MIME) || !soap->mime.boundary) + return SOAP_OK; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending MIME attachments\n")); + for (content = soap->mime.first; content; content = content->next) + if (soap_putmimehdr(soap, content) + || soap_send_raw(soap, content->ptr, content->size)) + return soap->error; + return soap_send3(soap, "\r\n--", soap->mime.boundary, "--"); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_dime(struct soap *soap) +{ soap->omode |= SOAP_ENC_DIME; + soap->dime.first = NULL; + soap->dime.last = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_mime(struct soap *soap, const char *boundary, const char *start) +{ soap->omode |= SOAP_ENC_MIME; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = soap_strdup(soap, boundary); + soap->mime.start = soap_strdup(soap, start); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_clr_dime(struct soap *soap) +{ soap->omode &= ~SOAP_ENC_DIME; + soap->dime.first = NULL; + soap->dime.last = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_clr_mime(struct soap *soap) +{ soap->omode &= ~SOAP_ENC_MIME; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = NULL; + soap->mime.start = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static struct soap_multipart* +soap_new_multipart(struct soap *soap, struct soap_multipart **first, struct soap_multipart **last, char *ptr, size_t size) +{ struct soap_multipart *content; + content = (struct soap_multipart*)soap_malloc(soap, sizeof(struct soap_multipart)); + if (content) + { content->next = NULL; + content->ptr = ptr; + content->size = size; + content->id = NULL; + content->type = NULL; + content->options = NULL; + content->encoding = SOAP_MIME_NONE; + content->location = NULL; + content->description = NULL; + if (!*first) + *first = content; + if (*last) + (*last)->next = content; + *last = content; + } + return content; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_dime_attachment(struct soap *soap, char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option) +{ struct soap_multipart *content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, ptr, size); + if (!content) + return SOAP_EOM; + content->id = soap_strdup(soap, id); + content->type = soap_strdup(soap, type); + content->options = soap_dime_option(soap, optype, option); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_mime_attachment(struct soap *soap, char *ptr, size_t size, enum soap_mime_encoding encoding, const char *type, const char *id, const char *location, const char *description) +{ struct soap_multipart *content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, ptr, size); + if (!content) + return SOAP_EOM; + content->id = soap_strdup(soap, id); + content->type = soap_strdup(soap, type); + content->encoding = encoding; + content->location = soap_strdup(soap, location); + content->description = soap_strdup(soap, description); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +struct soap_multipart* +SOAP_FMAC2 +soap_next_multipart(struct soap_multipart *content) +{ if (content) + return content->next; + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static void +soap_select_mime_boundary(struct soap *soap) +{ while (!soap->mime.boundary || soap_valid_mime_boundary(soap)) + { register char *s = soap->mime.boundary; + register size_t n = 0; + if (s) + n = strlen(s); + if (n < 16) + { n = 64; + s = soap->mime.boundary = (char*)soap_malloc(soap, n + 1); + if (!s) + return; + } + strcpy(s, "=="); + s += 2; + n -= 4; + while (n) + { *s++ = soap_base64o[soap_random & 0x3F]; + n--; + } + strcpy(s, "=="); + } + if (!soap->mime.start) + soap->mime.start = ""; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static int +soap_valid_mime_boundary(struct soap *soap) +{ register struct soap_multipart *content; + register size_t k = strlen(soap->mime.boundary); + for (content = soap->mime.first; content; content = content->next) + { if (content->ptr && content->size >= k) + { register const char *p = (const char*)content->ptr; + register size_t i; + for (i = 0; i < content->size - k; i++, p++) + if (!strncmp(p, soap->mime.boundary, k)) + return SOAP_ERR; + } + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ + +#ifdef WITH_COOKIES +/******************************************************************************/ +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_encode_cookie(const char *s, char *t, size_t len) +{ register int c; + register size_t n = len; + while ((c = *s++) && --n > 0) + { if (c > ' ' && c < 128 && !strchr("()<>@,;:\\\"/[]?={}", c)) + *t++ = c; + else if (n > 2) + { *t++ = '%'; + *t++ = (c >> 4) + (c > 159 ? '7' : '0'); + c &= 0xF; + *t++ = c + (c > 9 ? '7' : '0'); + n -= 2; + } + else + break; + } + *t = '\0'; + return len - n; +} + +/******************************************************************************/ +SOAP_FMAC1 +struct soap_cookie* +SOAP_FMAC2 +soap_cookie(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + size_t n; + if (!domain) + domain = soap->cookie_domain; + if (!path) + path = soap->cookie_path; + if (*path == '/') + path++; + n = strlen(path); + for (p = soap->cookies; p; p = p->next) + if (!strcmp(p->name, name) + && domain + && p->domain + && !strcmp(p->domain, domain) + && !strncmp(p->path, path, n)) + break; + return p; +} + +/******************************************************************************/ +SOAP_FMAC1 +struct soap_cookie* +SOAP_FMAC2 +soap_set_cookie(struct soap *soap, const char *name, const char *value, const char *domain, const char *path) +{ struct soap_cookie **p, *q; + int n; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set cookie: %s=%s domain=%s path=%s\n", name, value?value:"", domain?domain:"", path?path:"")); + if (!domain) + domain = soap->cookie_domain; + if (!path) + path = soap->cookie_path; + if (!path) + { soap_set_receiver_error(soap, "Cookie path not set", NULL, SOAP_HTTP_ERROR); + return NULL; + } + if (*path == '/') + path++; + q = soap_cookie(soap, name, domain, path); + if (!q) + { if ((q = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie)))) + { if ((q->name = (char*)SOAP_MALLOC(soap, strlen(name)+1))) + strcpy(q->name, name); + q->value = NULL; + q->domain = NULL; + q->path = NULL; + q->expire = -1; + q->version = 0; + q->secure = 0; + q->modified = 0; + for (p = &soap->cookies, n = soap->cookie_max; *p && n; p = &(*p)->next, n--) + if (!strcmp((*p)->name, name) && (*p)->path && strcmp((*p)->path, path) < 0) + break; + if (n) + { q->next = *p; + *p = q; + } + else + { SOAP_FREE(soap, q->name); + SOAP_FREE(soap, q); + q = NULL; + } + } + } + else + q->modified = 1; + if (q) + { if (q->value) + { SOAP_FREE(soap, q->value); + q->value = NULL; + } + if (q->domain) + { SOAP_FREE(soap, q->domain); + q->domain = NULL; + } + if (q->path) + { SOAP_FREE(soap, q->path); + q->path = NULL; + } + if (value && *value && (q->value = (char*)SOAP_MALLOC(soap, strlen(value)+1))) + strcpy(q->value, value); + if (domain && *domain && (q->domain = (char*)SOAP_MALLOC(soap, strlen(domain)+1))) + strcpy(q->domain, domain); + if (path && *path && (q->path = (char*)SOAP_MALLOC(soap, strlen(path)+1))) + strcpy(q->path, path); + q->session = 1; + q->env = 0; + } + return q; +} + +/******************************************************************************/ +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_clr_cookie(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie **p, *q; + if (!domain) + domain = soap->cookie_domain; + if (!domain) + { soap_set_receiver_error(soap, "Cookie domain not set", NULL, SOAP_HTTP_ERROR); + return; + } + if (!path) + path = soap->cookie_path; + if (!path) + { soap_set_receiver_error(soap, "Cookie path not set", NULL, SOAP_HTTP_ERROR); + return; + } + if (*path == '/') + path++; + for (p = &soap->cookies, q = *p; q; q = *p) + if (!strcmp(q->name, name) && !strcmp(q->domain, domain) && !strncmp(q->path, path, strlen(q->path))) + { if (q->value) + SOAP_FREE(soap, q->value); + if (q->domain) + SOAP_FREE(soap, q->domain); + if (q->path) + SOAP_FREE(soap, q->path); + *p = q->next; + SOAP_FREE(soap, q); + } + else + p = &q->next; +} + +/******************************************************************************/ +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + return p->value; + return NULL; +} + +/******************************************************************************/ +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_env_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path)) && p->env) + return p->value; + return NULL; +} + +/******************************************************************************/ +SOAP_FMAC1 +long +SOAP_FMAC2 +soap_cookie_expire(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + return p->expire; + return -1; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_cookie_expire(struct soap *soap, const char *name, long expire, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + { p->expire = expire; + p->modified = 1; + return SOAP_OK; + } + return SOAP_ERR; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + { p->session = 1; + p->modified = 1; + return SOAP_OK; + } + return SOAP_ERR; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_clr_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + { p->session = 0; + p->modified = 1; + return SOAP_OK; + } + return SOAP_ERR; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putsetcookies(struct soap *soap) +{ struct soap_cookie *p; + char *s, tmp[4096]; + const char *t; + for (p = soap->cookies; p; p = p->next) + { if (p->modified || !p->env) + { s = tmp; + if (p->name) + s += soap_encode_cookie(p->name, s, tmp-s+4064); + if (p->value && *p->value) + { *s++ = '='; + s += soap_encode_cookie(p->value, s, tmp-s+4064); + } + if (p->domain && (int)strlen(p->domain) < tmp-s+4064) + sprintf(s, ";Domain=\"%s\"", p->domain); + else if (soap->cookie_domain && (int)strlen(soap->cookie_domain) < tmp-s+4064) + sprintf(s, ";Domain=\"%s\"", soap->cookie_domain); + strcat(s, ";Path=\"/"); + if (p->path) + t = p->path; + else + t = soap->cookie_path; + if (t) + { if (*t == '/') + t++; + if ((int)strlen(t) < tmp-s+4064) + strcat(s, t); + } + s += strlen(s); + *s++ = '"'; + if (p->version > 0) + sprintf(s, ";Version=%u", p->version); + if (p->expire >= 0) + sprintf(s, ";Max-Age=%ld", p->expire); + if (p->secure) + strcat(s, ";Secure"); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set-Cookie: %s\n", tmp)); + if ((soap->error = soap->fposthdr(soap, "Set-Cookie", tmp))) + return soap->error; + } + } + return SOAP_OK; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putcookies(struct soap *soap, const char *domain, const char *path, int secure) +{ struct soap_cookie **p, *q; + unsigned int version = 0; + time_t now = time(NULL); + char *s, tmp[4096]; + p = &soap->cookies; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending cookies for domain=%s path=%s\n", domain, path)); + if (*path == '/') + path++; + while ((q = *p)) + { if (q->expire && now > q->expire) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie %s expired\n", q->name)); + SOAP_FREE(soap, q->name); + if (q->value) + SOAP_FREE(soap, q->value); + if (q->domain) + SOAP_FREE(soap, q->domain); + if (q->path) + SOAP_FREE(soap, q->path); + *p = q->next; + SOAP_FREE(soap, q); + } + else + { size_t domlen = 0; + if (q->domain) + { const char *s = strchr(q->domain, ':'); + if (s) + domlen = s - q->domain; + else + domlen = strlen(q->domain); + } + if ((!q->domain || !strncmp(q->domain, domain, domlen)) + && (!q->path || !strncmp(q->path, path, strlen(q->path))) + && (!q->secure || secure)) + { s = tmp; + if (q->version != version) + { sprintf(s, "$Version=%u;", q->version); + version = q->version; + } + if (q->name) + s += soap_encode_cookie(q->name, s, tmp-s+4080); + if (q->value && *q->value) + { *s++ = '='; + s += soap_encode_cookie(q->value, s, tmp-s+4080); + } + if (q->path && (int)strlen(q->path) < tmp-s+4080) + { sprintf(s, ";$Path=\"/%s\"", (*q->path == '/' ? q->path + 1 : q->path)); + s += strlen(s); + } + if (q->domain && (int)strlen(q->domain) < tmp-s+4080) + sprintf(s, ";$Domain=\"%s\"", q->domain); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie: %s\n", tmp)); + if ((soap->error = soap->fposthdr(soap, "Cookie", tmp))) + return soap->error; + } + p = &q->next; + } + } + return SOAP_OK; +} + +/******************************************************************************/ +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_getcookies(struct soap *soap, const char *val) +{ struct soap_cookie *p = NULL, *q; + const char *s; + char *t, tmp[4096]; /* cookie size is up to 4096 bytes [RFC2109] */ + char *domain = NULL; + char *path = NULL; + unsigned int version = 0; + time_t now = time(NULL); + if (!val) + return; + s = val; + while (*s) + { s = soap_decode_key(tmp, sizeof(tmp), s); + if (!soap_tag_cmp(tmp, "$Version")) + { if ((s = soap_decode_val(tmp, sizeof(tmp), s))) + { if (p) + p->version = (int)atol(tmp); + else + version = (int)atol(tmp); + } + } + else if (!soap_tag_cmp(tmp, "$Path")) + { s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) + strcpy(t, tmp); + } + else + t = NULL; + if (p) + { if (p->path) + SOAP_FREE(soap, p->path); + p->path = t; + } + else + { if (path) + SOAP_FREE(soap, path); + path = t; + } + } + else if (!soap_tag_cmp(tmp, "$Domain")) + { s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) + strcpy(t, tmp); + } + else + t = NULL; + if (p) + { if (p->domain) + SOAP_FREE(soap, p->domain); + p->domain = t; + } + else + { if (domain) + SOAP_FREE(soap, domain); + domain = t; + } + } + else if (p && !soap_tag_cmp(tmp, "Path")) + { if (p->path) + SOAP_FREE(soap, p->path); + s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { if ((p->path = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) + strcpy(p->path, tmp); + } + else + p->path = NULL; + } + else if (p && !soap_tag_cmp(tmp, "Domain")) + { if (p->domain) + SOAP_FREE(soap, p->domain); + s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { if ((p->domain = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) + strcpy(p->domain, tmp); + } + else + p->domain = NULL; + } + else if (p && !soap_tag_cmp(tmp, "Version")) + { s = soap_decode_val(tmp, sizeof(tmp), s); + p->version = (unsigned int)atol(tmp); + } + else if (p && !soap_tag_cmp(tmp, "Max-Age")) + { s = soap_decode_val(tmp, sizeof(tmp), s); + p->expire = now + atol(tmp); + } + else if (p && !soap_tag_cmp(tmp, "Expires")) + { struct tm T; + char a[3]; + static const char mns[] = "anebarprayunulugepctovec"; + s = soap_decode_val(tmp, sizeof(tmp), s); + if (strlen(tmp) > 20) + { memset((void*)&T, 0, sizeof(T)); + a[0] = tmp[4]; + a[1] = tmp[5]; + a[2] = '\0'; + T.tm_mday = (int)atol(a); + a[0] = tmp[8]; + a[1] = tmp[9]; + T.tm_mon = (strstr(mns, a) - mns) / 2; + a[0] = tmp[11]; + a[1] = tmp[12]; + T.tm_year = 100 + (int)atol(a); + a[0] = tmp[13]; + a[1] = tmp[14]; + T.tm_hour = (int)atol(a); + a[0] = tmp[16]; + a[1] = tmp[17]; + T.tm_min = (int)atol(a); + a[0] = tmp[19]; + a[1] = tmp[20]; + T.tm_sec = (int)atol(a); + p->expire = soap_timegm(&T); + } + } + else if (p && !soap_tag_cmp(tmp, "Secure")) + p->secure = 1; + else + { if (p) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie %s=%s domain=%s path=%s expire=%ld secure=%d\n", p->name, p->value?p->value:"", p->domain?p->domain:"", p->path?p->path:"", p->expire, p->secure)); + if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path))) + { q->version = p->version; + q->expire = p->expire; + q->secure = p->secure; + q->env = 1; + } + if (p->name) + SOAP_FREE(soap, p->name); + if (p->value) + SOAP_FREE(soap, p->value); + if (p->domain) + SOAP_FREE(soap, p->domain); + if (p->path) + SOAP_FREE(soap, p->path); + SOAP_FREE(soap, p); + } + if ((p = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie)))) + { p->name = (char*)SOAP_MALLOC(soap, strlen(tmp)+1); + strcpy(p->name, tmp); + s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { p->value = (char*)SOAP_MALLOC(soap, strlen(tmp)+1); + strcpy(p->value, tmp); + } + else + p->value = NULL; + p->domain = domain; + p->path = path; + p->expire = 0; + p->secure = 0; + p->version = version; + } + } + } + if (p) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie %s=%s domain=%s path=%s expire=%ld secure=%d\n", p->name, p->value?p->value:"", p->domain?p->domain:"", p->path?p->path:"", p->expire, p->secure)); + if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path))) + { q->version = p->version; + q->expire = p->expire; + q->secure = p->secure; + q->env = 1; + } + if (p->name) + SOAP_FREE(soap, p->name); + if (p->value) + SOAP_FREE(soap, p->value); + if (p->domain) + SOAP_FREE(soap, p->domain); + if (p->path) + SOAP_FREE(soap, p->path); + SOAP_FREE(soap, p); + } + if (domain) + SOAP_FREE(soap, domain); + if (path) + SOAP_FREE(soap, path); +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getenv_cookies(struct soap *soap) +{ struct soap_cookie *p; + const char *s; + char key[4096], val[4096]; /* cookie size is up to 4096 bytes [RFC2109] */ + if (!(s = getenv("HTTP_COOKIE"))) + return SOAP_ERR; + do + { s = soap_decode_key(key, sizeof(key), s); + s = soap_decode_val(val, sizeof(val), s); + p = soap_set_cookie(soap, key, val, NULL, NULL); + if (p) + p->env = 1; + } while (*s); + return SOAP_OK; +} + +/******************************************************************************/ +SOAP_FMAC1 +struct soap_cookie* +SOAP_FMAC2 +soap_copy_cookies(struct soap *soap) +{ struct soap_cookie *p, **q, *r; + q = &r; + for (p = soap->cookies; p; p = p->next) + { if (!(*q = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie)))) + return r; + **q = *p; + if (p->name) + { if (((*q)->name = (char*)SOAP_MALLOC(soap, strlen(p->name)+1))) + strcpy((*q)->name, p->name); + } + if (p->value) + { if (((*q)->value = (char*)SOAP_MALLOC(soap, strlen(p->value)+1))) + strcpy((*q)->value, p->value); + } + if (p->domain) + { if (((*q)->domain = (char*)SOAP_MALLOC(soap, strlen(p->domain)+1))) + strcpy((*q)->domain, p->domain); + } + if (p->path) + { if (((*q)->path = (char*)SOAP_MALLOC(soap, strlen(p->path)+1))) + strcpy((*q)->path, p->path); + } + q = &(*q)->next; + } + *q = NULL; + return r; +} + +/******************************************************************************/ +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_free_cookies(struct soap *soap) +{ struct soap_cookie *p; + for (p = soap->cookies; p; p = soap->cookies) + { soap->cookies = p->next; + SOAP_FREE(soap, p->name); + if (p->value) + SOAP_FREE(soap, p->value); + if (p->domain) + SOAP_FREE(soap, p->domain); + if (p->path) + SOAP_FREE(soap, p->path); + SOAP_FREE(soap, p); + } +} + +/******************************************************************************/ +#endif /* WITH_COOKIES */ + +/******************************************************************************/ +#ifdef WITH_GZIP +#ifndef PALM_1 +static int +soap_getgziphdr(struct soap *soap) +{ int i; + soap_wchar c, f = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get gzip header\n")); + for (i = 0; i < 9; i++) + { if ((int)(c = soap_get1(soap) == EOF)) + return soap->error = SOAP_EOF; + if (i == 2) + f = c; + } + if (f & 0x04) /* FEXTRA */ + { for (i = soap_get1(soap) | (soap_get1(soap) << 8); i; i--) + if ((int)soap_get1(soap) == EOF) + return soap->error = SOAP_EOF; + } + if (f & 0x08) /* FNAME */ + do + c = soap_get1(soap); + while (c && (int)c != EOF); + if ((int)c != EOF && (f & 0x10)) /* FCOMMENT */ + do + c = soap_get1(soap); + while (c && (int)f != EOF); + if ((int)c != EOF && (f & 0x01)) /* FHCRC */ + { if ((int)(c = soap_get1(soap)) != EOF) + c = soap_get1(soap); + } + if ((int)c == EOF) + return soap->error = SOAP_EOF; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_begin_recv(struct soap *soap) +{ soap_wchar c; + soap->error = SOAP_OK; + soap_free(soap); + soap_set_local_namespaces(soap); + soap->version = 0; /* don't assume we're parsing SOAP content by default */ +#ifndef WITH_NOIDREF + soap_free_iht(soap); +#endif + if ((soap->imode & SOAP_IO) == SOAP_IO_CHUNK) + soap->omode |= SOAP_IO_CHUNK; + soap->imode &= ~SOAP_IO; + soap->mode = soap->imode; + if (!soap->keep_alive) + { soap->buflen = 0; + soap->bufidx = 0; + } + if (!(soap->mode & SOAP_IO_KEEPALIVE)) + soap->keep_alive = 0; + soap->ahead = 0; + soap->peeked = 0; + soap->level = 0; + soap->part = SOAP_BEGIN; + soap->alloced = 0; + soap->count = 0; + soap->length = 0; + soap->cdata = 0; + *soap->endpoint = '\0'; + soap->action = NULL; +#ifndef WITH_LEANER + soap->dom = NULL; + soap->dime.chunksize = 0; + soap->dime.buflen = 0; + soap->dime.list = NULL; + soap->dime.first = NULL; + soap->dime.last = NULL; + soap->mime.list = NULL; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = NULL; + soap->mime.start = NULL; + soap->xlist = NULL; +#endif +#ifdef WIN32 +#ifndef UNDER_CE +#ifndef WITH_FASTCGI + if (!soap_valid_socket(soap->socket)) +#ifdef __BORLANDC__ + setmode((SOAP_SOCKET)soap->recvfd, O_BINARY); +#else + _setmode((SOAP_SOCKET)soap->recvfd, _O_BINARY); +#endif +#endif +#endif +#endif +#ifdef WITH_ZLIB + soap->mode &= ~SOAP_ENC_ZLIB; + soap->zlib_in = SOAP_ZLIB_NONE; + soap->zlib_out = SOAP_ZLIB_NONE; + soap->d_stream.next_in = Z_NULL; + soap->d_stream.avail_in = 0; + soap->d_stream.next_out = (Byte*)soap->buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + soap->z_ratio_in = 1.0; +#endif +#ifndef WITH_LEANER + if (soap->fprepareinit) + soap->fprepareinit(soap); +#endif + c = soap_getchar(soap); +#ifdef WITH_GZIP + if (c == 0x1F) + { if (soap_getgziphdr(soap)) + return soap->error; + if (inflateInit2(&soap->d_stream, -MAX_WBITS) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; + soap->zlib_state = SOAP_ZLIB_INFLATE; + soap->mode |= SOAP_ENC_ZLIB; + soap->zlib_in = SOAP_ZLIB_GZIP; + soap->z_crc = crc32(0L, NULL, 0); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n")); + memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); + /* should not chunk over plain transport, so why bother to check? */ + /* if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) */ + /* soap->z_buflen = soap->bufidx; */ + /* else */ + soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx); + soap->d_stream.avail_in = soap->buflen - soap->bufidx; + soap->z_buflen = soap->buflen; + soap->buflen = soap->bufidx; + c = soap_getchar(soap); + } +#endif +#ifndef WITH_LEANER + if (c == '-' && soap_get0(soap) == '-') + soap->mode |= SOAP_ENC_MIME; + else if ((c & 0xFFFC) == (SOAP_DIME_VERSION | SOAP_DIME_MB) && (soap_get0(soap) & 0xFFF0) == 0x20) + soap->mode |= SOAP_ENC_DIME; + else +#endif + { while (soap_blank(c)) + c = soap_getchar(soap); + } + if ((int)c == EOF) + return soap->error = SOAP_EOF; + soap_unget(soap, c); +#ifndef WITH_NOHTTP + /* if not XML or (start of)BOM or MIME/DIME/ZLIB, assume HTTP header */ + if (c != '<' && c != 0xEF && !(soap->mode & (SOAP_ENC_MIME | SOAP_ENC_DIME | SOAP_ENC_ZLIB))) + { soap->mode &= ~SOAP_IO; + soap->error = soap->fparse(soap); + if (soap->error && soap->error < SOAP_STOP) + { soap->keep_alive = 0; /* force close later */ + return soap->error; + } + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) + { soap->chunkbuflen = soap->buflen; + soap->buflen = soap->bufidx; + soap->chunksize = 0; + } +#ifndef WITH_LEANER + else if (soap->fpreparerecv && soap->buflen != soap->bufidx) + soap->fpreparerecv(soap, soap->buf + soap->bufidx, soap->buflen - soap->bufidx); +#endif +#ifdef WITH_ZLIB + if (soap->zlib_in != SOAP_ZLIB_NONE) + { /* fparse should not use soap_unget to push back last char */ +#ifdef WITH_GZIP + c = soap_get1(soap); + if (c == 0x1F) + { if (soap_getgziphdr(soap)) + return soap->error; + if (inflateInit2(&soap->d_stream, -MAX_WBITS) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; + soap->zlib_state = SOAP_ZLIB_INFLATE; + soap->z_crc = crc32(0L, NULL, 0); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n")); + } + else + { soap_revget1(soap); +#else + { +#endif + if (inflateInit(&soap->d_stream) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; + soap->zlib_state = SOAP_ZLIB_INFLATE; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate initialized\n")); + } + soap->mode |= SOAP_ENC_ZLIB; + memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); + soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx); + soap->d_stream.avail_in = soap->buflen - soap->bufidx; + soap->z_buflen = soap->buflen; + soap->buflen = soap->bufidx; + } +#endif + if (soap->error) + { if (soap->error == SOAP_FORM && soap->fform) + { soap->error = soap->fform(soap); + if (soap->error == SOAP_OK) + soap->error = SOAP_STOP; /* prevents further processing */ + } + return soap->error; + } + } +#endif +#ifndef WITH_LEANER + if (soap->mode & SOAP_ENC_MIME) + { if (soap_getmimehdr(soap)) + return soap->error; + if (soap_get_header_attribute(soap, soap->mime.first->type, "application/dime")) + soap->mode |= SOAP_ENC_DIME; + } + if (soap->mode & SOAP_ENC_DIME) + { if (soap_getdimehdr(soap)) + return soap->error; + if (soap->dime.flags & SOAP_DIME_CF) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked DIME SOAP message\n")); + soap->dime.chunksize = soap->dime.size; + if (soap->buflen - soap->bufidx >= soap->dime.chunksize) + { soap->dime.buflen = soap->buflen; + soap->buflen = soap->bufidx + soap->dime.chunksize; + } + else + soap->dime.chunksize -= soap->buflen - soap->bufidx; + } + soap->count = soap->buflen - soap->bufidx; + } +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_parse(struct soap *soap) +{ char header[SOAP_HDRLEN], *s; + unsigned short get = 0, status = 0, k = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Waiting for HTTP request/response...\n")); + *soap->endpoint = '\0'; + soap->length = 0; + soap->userid = NULL; + soap->passwd = NULL; + soap->action = NULL; + soap->authrealm = NULL; + do + { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) + return soap->error; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP status: %s\n", soap->msgbuf)); + for (;;) + { if (soap_getline(soap, header, SOAP_HDRLEN)) + { if (soap->error == SOAP_EOF) + { soap->error = SOAP_OK; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "EOF in HTTP header, continue anyway\n")); + break; + } + return soap->error; + } + if (!*header) + break; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP header: %s\n", header)); + s = strchr(header, ':'); + if (s) + { *s = '\0'; + do s++; + while (*s && *s <= 32); + if ((soap->error = soap->fparsehdr(soap, header, s))) + { if (soap->error < SOAP_STOP) + return soap->error; + status = soap->error; + soap->error = SOAP_OK; + } + } + } + if ((s = strchr(soap->msgbuf, ' '))) + { k = (unsigned short)soap_strtoul(s, &s, 10); + if (!soap_blank(*s)) + k = 0; + } + else + k = 0; + } while (k == 100); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Finished HTTP header parsing\n")); + s = strstr(soap->msgbuf, "HTTP/"); + if (s && s[7] != '1') + { if (soap->keep_alive == 1) + soap->keep_alive = 0; + if (k == 0 && (soap->omode & SOAP_IO) == SOAP_IO_CHUNK) /* k == 0 for HTTP request */ + { soap->imode |= SOAP_IO_CHUNK; + soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE; + } + } + if (soap->keep_alive < 0) + soap->keep_alive = 1; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Keep alive connection = %d\n", soap->keep_alive)); + if (s && (((get = !strncmp(soap->msgbuf, "GET ", 4))) || !strncmp(soap->msgbuf, "POST ", 5))) + { size_t m = strlen(soap->endpoint); + size_t n = m + (s - soap->msgbuf) - 5 - (!get); + if (n >= sizeof(soap->endpoint)) + n = sizeof(soap->endpoint) - 1; + strncpy(soap->path, soap->msgbuf + 4 + (!get), n - m); + soap->path[n - m] = '\0'; + strcat(soap->endpoint, soap->path); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Target endpoint='%s'\n", soap->endpoint)); + if (get) + { soap->error = soap->fget(soap); + if (soap->error == SOAP_OK) + soap->error = SOAP_STOP; /* prevents further processing */ + return soap->error; + } + if (status) + return soap->error = status; + return SOAP_OK; + } + if (k == 0 || (k >= 200 && k <= 299) || k == 400 || k == 500) + return SOAP_OK; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP error %d\n", k)); + return soap_set_receiver_error(soap, "HTTP error", soap->msgbuf, k); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_parse_header(struct soap *soap, const char *key, const char *val) +{ if (!soap_tag_cmp(key, "Host")) + { +#ifdef WITH_OPENSSL + if (soap->imode & SOAP_ENC_SSL) + strcpy(soap->endpoint, "https://"); + else +#endif + strcpy(soap->endpoint, "http://"); + strncat(soap->endpoint, val, sizeof(soap->endpoint) - 8); + soap->endpoint[sizeof(soap->endpoint) - 1] = '\0'; + } +#ifndef WITH_LEANER + else if (!soap_tag_cmp(key, "Content-Type")) + { if (soap_get_header_attribute(soap, val, "application/dime")) + soap->mode |= SOAP_ENC_DIME; + else if (soap_get_header_attribute(soap, val, "multipart/related") + || soap_get_header_attribute(soap, val, "multipart/form-data")) + { soap->mime.boundary = soap_strdup(soap, soap_get_header_attribute(soap, val, "boundary")); + soap->mime.start = soap_strdup(soap, soap_get_header_attribute(soap, val, "start")); + soap->mode |= SOAP_ENC_MIME; + } + } +#endif + else if (!soap_tag_cmp(key, "Content-Length")) + soap->length = soap_strtoul(val, NULL, 10); + else if (!soap_tag_cmp(key, "Content-Encoding")) + { if (!soap_tag_cmp(val, "deflate")) +#ifdef WITH_ZLIB + soap->zlib_in = SOAP_ZLIB_DEFLATE; +#else + return SOAP_ZLIB_ERROR; +#endif + else if (!soap_tag_cmp(val, "gzip")) +#ifdef WITH_GZIP + soap->zlib_in = SOAP_ZLIB_GZIP; +#else + return SOAP_ZLIB_ERROR; +#endif + } +#ifdef WITH_ZLIB + else if (!soap_tag_cmp(key, "Accept-Encoding")) + { +#ifdef WITH_GZIP + if (strchr(val, '*') || soap_get_header_attribute(soap, val, "gzip")) + soap->zlib_out = SOAP_ZLIB_GZIP; + else +#endif + if (strchr(val, '*') || soap_get_header_attribute(soap, val, "deflate")) + soap->zlib_out = SOAP_ZLIB_DEFLATE; + else + soap->zlib_out = SOAP_ZLIB_NONE; + } +#endif + else if (!soap_tag_cmp(key, "Transfer-Encoding")) + { soap->mode &= ~SOAP_IO; + if (!soap_tag_cmp(val, "chunked")) + soap->mode |= SOAP_IO_CHUNK; + } + else if (!soap_tag_cmp(key, "Connection")) + { if (!soap_tag_cmp(val, "keep-alive")) + soap->keep_alive = -soap->keep_alive; + else if (!soap_tag_cmp(val, "close")) + soap->keep_alive = 0; + } +#ifndef WITH_LEAN + else if (!soap_tag_cmp(key, "Authorization")) + { if (!soap_tag_cmp(val, "Basic *")) + { int n; + char *s; + soap_base642s(soap, val + 6, soap->tmpbuf, sizeof(soap->tmpbuf) - 1, &n); + soap->tmpbuf[n] = '\0'; + if ((s = strchr(soap->tmpbuf, ':'))) + { *s = '\0'; + soap->userid = soap_strdup(soap, soap->tmpbuf); + soap->passwd = soap_strdup(soap, s + 1); + } + } + } + else if (!soap_tag_cmp(key, "WWW-Authenticate")) + soap->authrealm = soap_strdup(soap, soap_get_header_attribute(soap, val + 6, "realm")); + else if (!soap_tag_cmp(key, "Expect")) + { if (!soap_tag_cmp(val, "100-continue")) + { if ((soap->error = soap->fposthdr(soap, "HTTP/1.1 100 Continue", NULL)) + || (soap->error = soap->fposthdr(soap, NULL, NULL))) + return soap->error; + } + } +#endif + else if (!soap_tag_cmp(key, "SOAPAction")) + { if (*val == '"') + { soap->action = soap_strdup(soap, val + 1); + soap->action[strlen(soap->action) - 1] = '\0'; + } + } + else if (!soap_tag_cmp(key, "Location")) + { strncpy(soap->endpoint, val, sizeof(soap->endpoint)); + soap->endpoint[sizeof(soap->endpoint) - 1] = '\0'; + } +#ifdef WITH_COOKIES + else if (!soap_tag_cmp(key, "Cookie") || !soap_tag_cmp(key, "Set-Cookie")) + soap_getcookies(soap, val); +#endif + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_get_header_attribute(struct soap *soap, const char *line, const char *key) +{ register const char *s = line; + if (s) + { while (*s) + { register short flag; + s = soap_decode_key(soap->tmpbuf, sizeof(soap->tmpbuf), s); + flag = soap_tag_cmp(soap->tmpbuf, key); + s = soap_decode_val(soap->tmpbuf, sizeof(soap->tmpbuf), s); + if (!flag) + return soap->tmpbuf; + } + } + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_decode_key(char *buf, size_t len, const char *val) +{ return soap_decode(buf, len, val, "=,;"); +} +#endif +#endif + +/******************************************************************************/ +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_decode_val(char *buf, size_t len, const char *val) +{ if (*val != '=') + { *buf = '\0'; + return val; + } + return soap_decode(buf, len, val + 1, ",;"); +} +#endif +#endif + +/******************************************************************************/ +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +#ifndef PALM_1 +static const char* +soap_decode(char *buf, size_t len, const char *val, const char *sep) +{ const char *s; + char *t = buf; + for (s = val; *s; s++) + if (*s != ' ' && *s != '\t' && !strchr(sep, *s)) + break; + if (*s == '"') + { s++; + while (*s && *s != '"' && --len) + *t++ = *s++; + } + else + { while (soap_notblank(*s) && !strchr(sep, *s) && --len) + { if (*s == '%') + { *t++ = ((s[1] >= 'A' ? (s[1] & 0x7) + 9 : s[1] - '0') << 4) + + (s[2] >= 'A' ? (s[2] & 0x7) + 9 : s[2] - '0'); + s += 3; + } + else + *t++ = *s++; + } + } + *t = '\0'; + while (*s && !strchr(sep, *s)) + s++; + return s; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_envelope_begin_out(struct soap *soap) +{ +#ifndef WITH_LEANER + size_t n = 0; + if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && soap->mime.start) + { const char *s; + if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) + s = "application/dime"; + else if (soap->version == 2) + s = "application/soap+xml; charset=utf-8"; + else + s = "text/xml; charset=utf-8"; + sprintf(soap->tmpbuf, "--%s\r\nContent-Type: %s\r\nContent-Transfer-Encoding: binary\r\nContent-ID: %s\r\n\r\n", soap->mime.boundary, s, soap->mime.start); + n = strlen(soap->tmpbuf); + if (soap_send_raw(soap, soap->tmpbuf, n)) + return soap->error; + } + if (soap->mode & SOAP_IO_LENGTH) + soap->dime.size = soap->count; /* DIME in MIME correction */ + if (!(soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME)) + { if (soap_putdimehdr(soap)) + return soap->error; + } +#endif + soap->part = SOAP_IN_ENVELOPE; + return soap_element_begin_out(soap, "SOAP-ENV:Envelope", 0, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_envelope_end_out(struct soap *soap) +{ if (soap_element_end_out(soap, "SOAP-ENV:Envelope")) + return soap->error; +#ifndef WITH_LEANER + if ((soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) + { soap->dime.size = soap->count - soap->dime.size; /* DIME in MIME correction */ + sprintf(soap->id, soap->dime_id_format, 0); + soap->dime.id = soap->id; + if (soap->local_namespaces) + { if (soap->local_namespaces[0].out) + soap->dime.type = (char*)soap->local_namespaces[0].out; + else + soap->dime.type = (char*)soap->local_namespaces[0].ns; + } + soap->dime.options = NULL; + soap->dime.flags = SOAP_DIME_MB | SOAP_DIME_ABSURI; + if (!soap->dime.first) + soap->dime.flags |= SOAP_DIME_ME; + soap->count += 12 + ((strlen(soap->dime.id)+3)&(~3)) + ((strlen(soap->dime.type)+3)&(~3)); + } + if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) + return soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3); +#endif + soap->part = SOAP_END_ENVELOPE; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_envelope_begin_in(struct soap *soap) +{ register struct Namespace *p; + soap->part = SOAP_IN_ENVELOPE; + if (soap_element_begin_in(soap, "SOAP-ENV:Envelope", 0)) + return soap->error = SOAP_VERSIONMISMATCH; + p = soap->local_namespaces; + if (p) + { const char *ns = p[0].out; + if (!ns) + ns = p[0].ns; + if (!strcmp(ns, soap_env1)) + { soap->version = 1; /* make sure we use SOAP 1.1 */ + if (p[1].out) + SOAP_FREE(soap, p[1].out); + if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc1)))) + strcpy(p[1].out, soap_enc1); + } + else if (!strcmp(ns, soap_env2)) + { soap->version = 2; /* make sure we use SOAP 1.2 */ + if (p[1].out) + SOAP_FREE(soap, p[1].out); + if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc2)))) + strcpy(p[1].out, soap_enc2); + } + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_envelope_end_in(struct soap *soap) +{ soap->part = SOAP_END_ENVELOPE; + return soap_element_end_in(soap, "SOAP-ENV:Envelope"); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_body_begin_out(struct soap *soap) +{ soap->part = SOAP_IN_BODY; + if (soap->version == 1) + soap->encoding = 1; +#ifndef WITH_LEAN + if ((soap->mode & SOAP_XML_SEC) && soap_set_attr(soap, "wsu:Id", "Body")) + return soap->error; +#endif + if (soap_element(soap, "SOAP-ENV:Body", 0, NULL)) + return soap->error; + return soap_element_start_end_out(soap, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_body_end_out(struct soap *soap) +{ if (soap_element_end_out(soap, "SOAP-ENV:Body")) + return soap->error; + soap->part = SOAP_END_BODY; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_body_begin_in(struct soap *soap) +{ soap->part = SOAP_IN_BODY; + if (soap_element_begin_in(soap, "SOAP-ENV:Body", 0)) + return soap->error; + if (!soap->body) + soap->part = SOAP_NO_BODY; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_body_end_in(struct soap *soap) +{ if (soap->part == SOAP_NO_BODY) + return SOAP_OK; + soap->part = SOAP_END_BODY; + return soap_element_end_in(soap, "SOAP-ENV:Body"); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv_header(struct soap *soap) +{ if (soap_getheader(soap) && soap->error == SOAP_TAG_MISMATCH) + soap->error = SOAP_OK; + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_endpoint(struct soap *soap, const char *endpoint) +{ register const char *s; + register size_t i, n; + soap->endpoint[0] = '\0'; + soap->host[0] = '\0'; + soap->path[0] = '/'; + soap->path[1] = '\0'; + soap->port = 80; + if (!endpoint || !*endpoint) + return; + if (!strncmp(endpoint, "https:", 6)) + soap->port = 443; + strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint) - 1); + s = strchr(endpoint, ':'); + if (s && s[1] == '/' && s[2] == '/') + s += 3; + else + s = endpoint; + n = strlen(s); + if (n >= sizeof(soap->host)) + n = sizeof(soap->host) - 1; +#ifdef WITH_IPV6 + if (s[0] == '[') + { s++; + for (i = 0; i < n; i++) + { soap->host[i] = s[i]; + if (s[i] == ']') + { s++; + break; + } + } + } + else + { for (i = 0; i < n; i++) + { soap->host[i] = s[i]; + if (s[i] == '/' || s[i] == ':') + break; + } + } +#else + for (i = 0; i < n; i++) + { soap->host[i] = s[i]; + if (s[i] == '/' || s[i] == ':') + break; + } +#endif + soap->host[i] = '\0'; + if (s[i] == ':') + { soap->port = (int)atol(s + i + 1); + for (i++; i < n; i++) + if (s[i] == '/') + break; + } + if (s[i]) + { strncpy(soap->path, s + i, sizeof(soap->path)); + soap->path[sizeof(soap->path) - 1] = '\0'; + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_connect(struct soap *soap, const char *endpoint, const char *action) +{ return soap_connect_command(soap, SOAP_POST, endpoint, action); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_connect_command(struct soap *soap, int http_command, const char *endpoint, const char *action) +{ char host[sizeof(soap->host)]; + int port; + size_t count; + soap->error = SOAP_OK; + strcpy(host, soap->host); /* save to compare */ + port = soap->port; /* save to compare */ + soap_set_endpoint(soap, endpoint); +#ifndef WITH_LEANER + if (soap->fconnect) + { if ((soap->error = soap->fconnect(soap, endpoint, soap->host, soap->port))) + return soap->error; + } + else +#endif + if (soap->fopen && *soap->host) + { soap->status = http_command; + if (!soap->keep_alive || !soap_valid_socket(soap->socket) || strcmp(soap->host, host) || soap->port != port || !soap->fpoll || soap->fpoll(soap)) + { soap->keep_alive = 0; /* to force close */ + soap->omode &= ~SOAP_IO_UDP; /* to force close */ + soap_closesock(soap); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Connect/reconnect to host='%s' path='%s' port=%d\n", soap->host, soap->path, soap->port)); +#ifdef WITH_UDP + if (!strncmp(endpoint, "soap.udp:", 9)) + soap->omode |= SOAP_IO_UDP; +#endif + soap->socket = soap->fopen(soap, endpoint, soap->host, soap->port); + if (soap->error) + return soap->error; + soap->keep_alive = ((soap->omode & SOAP_IO_KEEPALIVE) != 0); + } + } + count = soap_count_attachments(soap); + if (soap_begin_send(soap)) + return soap->error; +#ifndef WITH_NOHTTP + if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML) && endpoint) + { unsigned int k = soap->mode; + soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB); + if ((k & SOAP_IO) != SOAP_IO_FLUSH) + soap->mode |= SOAP_IO_BUFFER; + if ((soap->error = soap->fpost(soap, endpoint, soap->host, soap->port, soap->path, action, count))) + return soap->error; +#ifndef WITH_LEANER + if ((k & SOAP_IO) == SOAP_IO_CHUNK) + { if (soap_flush(soap)) + return soap->error; + } +#endif + soap->mode = k; + } + else if (action) + soap->action = soap_strdup(soap, action); + if (http_command != SOAP_POST) + return soap_end_send(soap); +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_s2base64(struct soap *soap, const unsigned char *s, char *t, int n) +{ register int i; + register unsigned long m; + register char *p; + if (!t) + t = (char*)soap_malloc(soap, (n + 2) / 3 * 4 + 1); + if (!t) + { soap->error = SOAP_EOM; + return NULL; + } + p = t; + t[0] = '\0'; + if (!s) + return p; + for (; n > 2; n -= 3, s += 3) + { m = s[0]; + m = (m << 8) | s[1]; + m = (m << 8) | s[2]; + for (i = 4; i > 0; m >>= 6) + t[--i] = soap_base64o[m & 0x3F]; + t += 4; + } + t[0] = '\0'; + if (n > 0) + { m = 0; + for (i = 0; i < n; i++) + m = (m << 8) | *s++; + for (; i < 3; i++) + m <<= 8; + for (i++; i > 0; m >>= 6) + t[--i] = soap_base64o[m & 0x3F]; + for (i = 3; i > n; i--) + t[i] = '='; + t[4] = '\0'; + } + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_base642s(struct soap *soap, const char *s, char *t, size_t l, int *n) +{ register int i, j, c; + register unsigned long m; + register const char *p; + if (!s || !*s) + { if (n) + *n = 0; + if (soap->error) + return NULL; + return SOAP_NON_NULL; + } + if (!t) + { l = (strlen(s) + 3) / 4 * 3; + t = (char*)soap_malloc(soap, l); + } + if (!t) + { soap->error = SOAP_EOM; + return NULL; + } + p = t; + if (n) + *n = 0; + for (;;) + { for (i = 0; i < SOAP_BLKLEN; i++) + { m = 0; + j = 0; + while (j < 4) + { c = *s++; + if (c == '=' || !c) + { i *= 3; + switch (j) + { case 2: + *t++ = (char)((m >> 4) & 0xFF); + i++; + break; + case 3: + *t++ = (char)((m >> 10) & 0xFF); + *t++ = (char)((m >> 2) & 0xFF); + i += 2; + } + if (n) + *n += i; + return p; + } + c -= '+'; + if (c >= 0 && c <= 79) + { m = (m << 6) + soap_base64i[c]; + j++; + } + } + *t++ = (char)((m >> 16) & 0xFF); + *t++ = (char)((m >> 8) & 0xFF); + *t++ = (char)(m & 0xFF); + if (l < 3) + { if (n) + *n += i; + return p; + } + l -= 3; + } + if (n) + *n += 3 * SOAP_BLKLEN; + } +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_s2hex(struct soap *soap, const unsigned char *s, char *t, int n) +{ register char *p; + if (!t) + t = (char*)soap_malloc(soap, 2 * n + 1); + if (!t) + { soap->error = SOAP_EOM; + return NULL; + } + p = t; + t[0] = '\0'; + if (s) + { for (; n > 0; n--) + { register int m = *s++; + *t++ = (char)((m >> 4) + (m > 159 ? 'a' - 10 : '0')); + m &= 0x0F; + *t++ = (char)(m + (m > 9 ? 'a' - 10 : '0')); + } + } + *t++ = '\0'; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_hex2s(struct soap *soap, const char *s, char *t, size_t l, int *n) +{ register const char *p; + if (!s || !*s) + { if (n) + *n = 0; + if (soap->error) + return NULL; + return SOAP_NON_NULL; + } + if (!t) + { l = strlen(s) / 2; + t = (char*)soap_malloc(soap, l); + } + if (!t) + { soap->error = SOAP_EOM; + return NULL; + } + p = t; + while (l) + { register int d1, d2; + d1 = *s++; + if (!d1) + break; + d2 = *s++; + if (!d2) + break; + *t++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'); + l--; + } + if (n) + *n = t - p; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_puthttphdr(struct soap *soap, int status, size_t count) +{ register const char *s = NULL; + register int err = SOAP_OK; +#ifndef WITH_LEANER + register const char *r = NULL; +#endif + if (status == SOAP_FILE && soap->http_content) + s = soap->http_content; + else if (status == SOAP_HTML) + s = "text/html; charset=utf-8"; + else if (count) + { if (soap->version == 2) + s = "application/soap+xml; charset=utf-8"; + else + s = "text/xml; charset=utf-8"; + } +#ifndef WITH_LEANER + if (soap->mode & (SOAP_ENC_DIME | SOAP_ENC_MTOM)) + { if (soap->mode & SOAP_ENC_MTOM) + { r = s; + s = "application/xop+xml; charset=utf-8"; + } + else + s = "application/dime"; + } + if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && soap->status != SOAP_GET) + { register const char *t = strchr(s, ';'); + sprintf(soap->tmpbuf, "multipart/related; boundary=\"%s\"; type=\"", soap->mime.boundary); + if (t) + strncat(soap->tmpbuf, s, t - s); + else + strcat(soap->tmpbuf, s); + if (soap->mime.start) + { strcat(soap->tmpbuf, "\"; start=\""); + strcat(soap->tmpbuf, soap->mime.start); + } + strcat(soap->tmpbuf, "\""); + if (r) + { strcat(soap->tmpbuf, "; start-info=\""); + strcat(soap->tmpbuf, r); + strcat(soap->tmpbuf, "\""); + } + s = soap->tmpbuf; + } +#endif + if (s && (err = soap->fposthdr(soap, "Content-Type", s))) + return err; +#ifdef WITH_ZLIB + if (soap->omode & SOAP_ENC_ZLIB) + { +#ifdef WITH_GZIP + err = soap->fposthdr(soap, "Content-Encoding", "gzip"); +#else + err = soap->fposthdr(soap, "Content-Encoding", "deflate"); +#endif + if (err) + return err; + } +#endif +#ifndef WITH_LEANER + if ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK) + err = soap->fposthdr(soap, "Transfer-Encoding", "chunked"); + else +#endif + if (soap->status != SOAP_GET) + { sprintf(soap->tmpbuf, "%lu", (unsigned long)count); + err = soap->fposthdr(soap, "Content-Length", soap->tmpbuf); + } + if (err) + return err; + return soap->fposthdr(soap, "Connection", soap->keep_alive ? "keep-alive" : "close"); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_get(struct soap *soap) +{ return SOAP_GET_METHOD; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_post(struct soap *soap, const char *endpoint, const char *host, int port, const char *path, const char *action, size_t count) +{ register const char *s; + register int err; + if (soap->status == SOAP_GET) + s = "GET"; + else + s = "POST"; +#ifdef PALM + if (!endpoint || (strncmp(endpoint, "http:", 5) && strncmp(endpoint, "https:", 6) && strncmp(endpoint, "httpg:", 6)) && strncmp(endpoint, "_beam:", 6) && strncmp(endpoint, "_local:", 7) && strncmp(endpoint, "_btobex:", 8)) +#else + if (!endpoint || (strncmp(endpoint, "http:", 5) && strncmp(endpoint, "https:", 6) && strncmp(endpoint, "httpg:", 6))) +#endif + return SOAP_OK; + if (soap->proxy_host && strncmp(endpoint, "https:", 6)) + sprintf(soap->tmpbuf, "%s %s HTTP/%s", s, endpoint, soap->http_version); + else + sprintf(soap->tmpbuf, "%s /%s HTTP/%s", s, (*path == '/' ? path + 1 : path), soap->http_version); + if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return err; + if (port != 80) + sprintf(soap->tmpbuf, "%s:%d", host, port); + else + strcpy(soap->tmpbuf, host); + if ((err = soap->fposthdr(soap, "Host", soap->tmpbuf)) + || (err = soap->fposthdr(soap, "User-Agent", "gSOAP/2.7")) + || (err = soap_puthttphdr(soap, SOAP_OK, count))) + return err; +#ifdef WITH_ZLIB +#ifdef WITH_GZIP + if ((err = soap->fposthdr(soap, "Accept-Encoding", "gzip, deflate"))) +#else + if ((err = soap->fposthdr(soap, "Accept-Encoding", "deflate"))) +#endif + return err; +#endif +#ifndef WITH_LEAN + if (soap->userid && soap->passwd && strlen(soap->userid) + strlen(soap->passwd) < 761) + { sprintf(soap->tmpbuf + 262, "%s:%s", soap->userid, soap->passwd); + strcpy(soap->tmpbuf, "Basic "); + soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, strlen(soap->tmpbuf + 262)); + if ((err = soap->fposthdr(soap, "Authorization", soap->tmpbuf))) + return err; + } + if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761) + { sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd); + strcpy(soap->tmpbuf, "Basic "); + soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, strlen(soap->tmpbuf + 262)); + if ((err = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf))) + return err; + } +#endif +#ifdef WITH_COOKIES +#ifdef WITH_OPENSSL + if (soap_putcookies(soap, host, path, soap->ssl != NULL)) + return soap->error; +#else + if (soap_putcookies(soap, host, path, 0)) + return soap->error; +#endif +#endif + if (action && soap->version == 1) + { sprintf(soap->tmpbuf, "\"%s\"", action); + if ((err = soap->fposthdr(soap, "SOAPAction", soap->tmpbuf))) + return err; + } + return soap->fposthdr(soap, NULL, NULL); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_send_header(struct soap *soap, const char *s) +{ register const char *t; + do + { t = strchr(s, '\n'); /* disallow \n in HTTP headers */ + if (!t) + t = s + strlen(s); + if (soap_send_raw(soap, s, t - s)) + return soap->error; + s = t + 1; + } while (*t); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_post_header(struct soap *soap, const char *key, const char *val) +{ if (key) + { if (http_send_header(soap, key)) + return soap->error; + if (val && (soap_send_raw(soap, ": ", 2) || http_send_header(soap, val))) + return soap->error; + } + return soap_send_raw(soap, "\r\n", 2); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_response(struct soap *soap, int status, size_t count) +{ register int err; +#ifdef WMW_RPM_IO + if (soap->rpmreqid) + httpOutputEnable(soap->rpmreqid); +#endif + if (!status || status == SOAP_HTML || status == SOAP_FILE) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "OK 200\n")); +#ifdef WMW_RPM_IO + if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */ +#else + if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application */ +#endif + { sprintf(soap->tmpbuf, "HTTP/%s 200 OK", soap->http_version); + if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return err; + } + else if ((err = soap->fposthdr(soap, "Status", "200 OK"))) + return err; + } + else if (status > 200 && status < 600) + { sprintf(soap->tmpbuf, "HTTP/%s %d %s", soap->http_version, status, http_error(soap, status)); + if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return err; +#ifndef WITH_LEAN + if (status == 401) + { sprintf(soap->tmpbuf, "Basic realm=\"%s\"", soap->authrealm ? soap->authrealm : "gSOAP Web Service"); + if ((err = soap->fposthdr(soap, "WWW-Authenticate", soap->tmpbuf))) + return err; + } + else if ((status >= 301 && status <= 303) || status == 307) + { if ((err = soap->fposthdr(soap, "Location", soap->endpoint))) + return err; + } +#endif + } + else + { const char *s = *soap_faultcode(soap); + if (soap->version == 2 && !strcmp(s, "SOAP-ENV:Sender")) + s = "400 Bad Request"; + else + s = "500 Internal Server Error"; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error %s (status=%d)\n", s, status)); +#ifdef WMW_RPM_IO + if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */ +#else + if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application */ +#endif + { sprintf(soap->tmpbuf, "HTTP/%s %s", soap->http_version, s); + if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return err; + } + else if ((err = soap->fposthdr(soap, "Status", s))) + return err; + } + if ((err = soap->fposthdr(soap, "Server", "gSOAP/2.7")) + || (err = soap_puthttphdr(soap, status, count))) + return err; +#ifdef WITH_COOKIES + if (soap_putsetcookies(soap)) + return soap->error; +#endif + return soap->fposthdr(soap, NULL, NULL); +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_response(struct soap *soap, int status) +{ register size_t count; + if (!(soap->omode & (SOAP_ENC_XML | SOAP_IO_STORE /* this tests for chunking too */)) + && (status == SOAP_HTML || status == SOAP_FILE)) + { soap->omode &= ~SOAP_IO; + soap->omode |= SOAP_IO_STORE; + } + soap->status = status; + count = soap_count_attachments(soap); + if (soap_begin_send(soap)) + return soap->error; +#ifndef WITH_NOHTTP + if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML)) + { register int n = soap->mode; + soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB); + if ((n & SOAP_IO) != SOAP_IO_FLUSH) + soap->mode |= SOAP_IO_BUFFER; + if ((soap->error = soap->fresponse(soap, status, count))) + return soap->error; +#ifndef WITH_LEANER + if ((n & SOAP_IO) == SOAP_IO_CHUNK) + { if (soap_flush(soap)) + return soap->error; + } +#endif + soap->mode = n; + } +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static const char* +soap_set_validation_fault(struct soap *soap, const char *s, const char *t) +{ if (*soap->tag) + sprintf(soap->msgbuf, "Validation constraint violation: %s%s in element <%s>", s, t?t:SOAP_STR_EOS, soap->tag); + else + sprintf(soap->msgbuf, "Validation constraint violation: %s%s", s, t?t:SOAP_STR_EOS); + return soap->msgbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_fault(struct soap *soap) +{ const char **c = soap_faultcode(soap); + const char **s = soap_faultstring(soap); + if (!*c && !*s && soap->fseterror) + soap->fseterror(soap, c, s); + if (!*c) + { if (soap->version == 2) + *c = "SOAP-ENV:Sender"; + else + *c = "SOAP-ENV:Client"; + } + if (*s) + return; + switch (soap->error) + { +#ifndef WITH_LEAN + case SOAP_CLI_FAULT: + *s = "Client fault"; + break; + case SOAP_SVR_FAULT: + *s = "Server fault"; + break; + case SOAP_TAG_MISMATCH: + *s = soap_set_validation_fault(soap, "tag name or namespace mismatch", NULL); + break; + case SOAP_TYPE: + *s = soap_set_validation_fault(soap, "data type mismatch ", soap->type); + break; + case SOAP_SYNTAX_ERROR: + *s = "Well-formedness violation"; + break; + case SOAP_NO_TAG: + *s = "No XML element tag"; + break; + case SOAP_MUSTUNDERSTAND: + *c = "SOAP-ENV:MustUnderstand"; + sprintf(soap->msgbuf, "The data in element '%s' must be understood but cannot be handled", soap->tag); + *s = soap->msgbuf; + break; + case SOAP_VERSIONMISMATCH: + *c = "SOAP-ENV:VersionMismatch"; + *s = "SOAP version mismatch or invalid SOAP message"; + break; + case SOAP_DATAENCODINGUNKNOWN: + *c = "SOAP-ENV:DataEncodingUnknown"; + *s = "Unsupported SOAP data encoding"; + break; + case SOAP_NAMESPACE: + *s = soap_set_validation_fault(soap, "namespace mismatch", NULL); + break; + case SOAP_USER_ERROR: + *s = "User error"; + break; + case SOAP_FATAL_ERROR: + *s = "Fatal error"; + break; + case SOAP_NO_METHOD: + sprintf(soap->msgbuf, "Method '%s' not implemented: method name or namespace not recognized", soap->tag); + *s = soap->msgbuf; + break; + case SOAP_GET_METHOD: + *s = "HTTP GET method not implemented"; + break; + case SOAP_EOM: + *s = "Out of memory"; + break; + case SOAP_IOB: + *s = "Array index out of bounds"; + break; + case SOAP_NULL: + *s = soap_set_validation_fault(soap, "nil not allowed", NULL); + break; + case SOAP_DUPLICATE_ID: + *s = soap_set_validation_fault(soap, "multiple definitions of id ", soap->id); + if (soap->version == 2) + *soap_faultsubcode(soap) = "SOAP-ENC:DuplicateID"; + break; + case SOAP_MISSING_ID: + *s = soap_set_validation_fault(soap, "missing id for ref ", soap->id); + if (soap->version == 2) + *soap_faultsubcode(soap) = "SOAP-ENC:MissingID"; + break; + case SOAP_HREF: + *s = soap_set_validation_fault(soap, "incompatible object ref ", soap->id); + break; + case SOAP_FAULT: + break; +#ifndef WITH_NOIO + case SOAP_UDP_ERROR: + *s = "Message too large for UDP packet"; + break; + case SOAP_TCP_ERROR: + *s = tcp_error(soap); + break; +#endif + case SOAP_HTTP_ERROR: + *s = "HTTP error"; + break; + case SOAP_SSL_ERROR: +#ifdef WITH_OPENSSL + *s = "SSL error"; +#else + *s = "OpenSSL not installed: recompile with -DWITH_OPENSSL"; +#endif + break; + case SOAP_PLUGIN_ERROR: + *s = "Plugin registry error"; + break; + case SOAP_DIME_ERROR: + *s = "DIME format error"; + break; + case SOAP_DIME_HREF: + *s = "DIME href to missing attachment"; + break; + case SOAP_DIME_MISMATCH: + *s = "DIME version/transmission error"; + break; + case SOAP_DIME_END: + *s = "End of DIME error"; + break; + case SOAP_MIME_ERROR: + *s = "MIME format error"; + break; + case SOAP_MIME_HREF: + *s = "MIME href to missing attachment"; + break; + case SOAP_MIME_END: + *s = "End of MIME error"; + break; + case SOAP_ZLIB_ERROR: +#ifdef WITH_ZLIB + sprintf(soap->msgbuf, "Zlib/gzip error: '%s'", soap->d_stream.msg?soap->d_stream.msg:""); + *s = soap->msgbuf; +#else + *s = "Zlib/gzip not installed for (de)compression: recompile with -DWITH_GZIP"; +#endif + break; + case SOAP_REQUIRED: + *s = soap_set_validation_fault(soap, "missing required attribute", NULL); + break; + case SOAP_PROHIBITED: + *s = soap_set_validation_fault(soap, "prohibited attribute present", NULL); + break; + case SOAP_OCCURS: + *s = soap_set_validation_fault(soap, "min/maxOccurs violation", NULL); + break; + case SOAP_LENGTH: + *s = soap_set_validation_fault(soap, "content length violation", NULL); + break; + case SOAP_STOP: + *s = "Stopped: no response sent"; + break; +#endif + case SOAP_EOF: +#ifndef WITH_NOIO + sprintf(soap->msgbuf, "End of file or no input: '%s'", soap_strerror(soap)); + *s = soap->msgbuf; + break; +#else + *s = "End of file or no input"; + break; +#endif + default: +#ifndef WITH_NOHTTP +#ifndef WITH_LEAN + if (soap->error > 200 && soap->error < 600) + { sprintf(soap->msgbuf, "HTTP Error: %d %s", soap->error, http_error(soap, soap->error)); + *s = soap->msgbuf; + } + else +#endif +#endif + { sprintf(soap->msgbuf, "Error %d", soap->error); + *s = soap->msgbuf; + } + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send_fault(struct soap *soap) +{ register int status = soap->error; + int r = 1; + if (status == SOAP_STOP) + return status; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Sending back fault struct for error code %d\n", soap->error)); + soap->keep_alive = 0; /* to terminate connection */ + soap_set_fault(soap); +#ifndef WITH_NOIO +#ifndef WITH_LEAN + if (soap_valid_socket(soap->socket)) + { struct timeval timeout; + fd_set rfd, sfd; + timeout.tv_sec = 0; + timeout.tv_usec = 0; + FD_ZERO(&rfd); + FD_ZERO(&sfd); + FD_SET((SOAP_SOCKET)soap->socket, &rfd); + FD_SET((SOAP_SOCKET)soap->socket, &sfd); + r = select((SOAP_SOCKET)(soap->socket + 1), &rfd, &sfd, NULL, &timeout); + if (r > 0) + { if (!FD_ISSET((SOAP_SOCKET)soap->socket, &sfd) + || (FD_ISSET((SOAP_SOCKET)soap->socket, &rfd) + && recv((SOAP_SOCKET)soap->socket, soap->tmpbuf, 1, MSG_PEEK) < 0)) + r = 0; + } + } +#endif +#endif + if ((status != SOAP_EOF || (!soap->recv_timeout && !soap->send_timeout)) && r > 0) + { soap->error = SOAP_OK; + soap_serializeheader(soap); + soap_serializefault(soap); + soap_begin_count(soap); + if (soap->mode & SOAP_IO_LENGTH) + { soap_envelope_begin_out(soap); + soap_putheader(soap); + soap_body_begin_out(soap); + soap_putfault(soap); + soap_body_end_out(soap); + soap_envelope_end_out(soap); + } + soap_end_count(soap); + if (soap_response(soap, status) + || soap_envelope_begin_out(soap) + || soap_putheader(soap) + || soap_body_begin_out(soap) + || soap_putfault(soap) + || soap_body_end_out(soap) + || soap_envelope_end_out(soap)) + return soap_closesock(soap); + soap_end_send(soap); + } + soap->error = status; + return soap_closesock(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv_fault(struct soap *soap) +{ register int status = soap->error; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Receiving SOAP Fault\n")); + soap->error = SOAP_OK; + if (soap_getfault(soap)) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Error: soap_get_soapfault() failed. Is this a SOAP message at all?\n")); + *soap_faultcode(soap) = (soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client"); + soap->error = status; + soap_set_fault(soap); + } + else + { register const char *s = *soap_faultcode(soap); + if (!soap_match_tag(soap, s, "SOAP-ENV:Server") || !soap_match_tag(soap, s, "SOAP-ENV:Receiver")) + status = SOAP_SVR_FAULT; + else if (!soap_match_tag(soap, s, "SOAP-ENV:Client") || !soap_match_tag(soap, s, "SOAP-ENV:Sender")) + status = SOAP_CLI_FAULT; + else if (!soap_match_tag(soap, s, "SOAP-ENV:MustUnderstand")) + status = SOAP_MUSTUNDERSTAND; + else if (!soap_match_tag(soap, s, "SOAP-ENV:VersionMismatch")) + status = SOAP_VERSIONMISMATCH; + else + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Fault code %s\n", s)); + status = SOAP_FAULT; + } + if (soap_body_end_in(soap) + || soap_envelope_end_in(soap) + || soap_end_recv(soap)) + return soap_closesock(soap); + soap->error = status; + } + return soap_closesock(soap); +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send_empty_response(struct soap *soap) +{ soap->count = 0; + if (soap_response(soap, SOAP_OK) || soap_end_send(soap)) + return soap_closesock(soap); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv_empty_response(struct soap *soap) +{ if (soap_begin_recv(soap) || soap_end_recv(soap)) + return soap_closesock(soap); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static const char* +soap_strerror(struct soap *soap) +{ register int err = soap->errnum; + if (err) + { +#ifndef WIN32 + return strerror(err); +#else + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0, (LPTSTR)&soap->errorstr, sizeof(soap->errorstr), NULL); + return soap->errorstr; +#endif + } + return "Operation interrupted or timed out"; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +static int +soap_set_error(struct soap *soap, const char *faultcode, const char *faultsubcode, const char *faultstring, const char *faultdetail, int soaperror) +{ *soap_faultcode(soap) = faultcode; + if (faultsubcode) + *soap_faultsubcode(soap) = faultsubcode; + *soap_faultstring(soap) = faultstring; + if (faultdetail && *faultdetail) + { register const char **s = soap_faultdetail(soap); + if (s) + *s = faultdetail; + } + return soap->error = soaperror; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_sender_error(struct soap *soap, const char *faultstring, const char *faultdetail, int soaperror) +{ return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", NULL, faultstring, faultdetail, soaperror); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_receiver_error(struct soap *soap, const char *faultstring, const char *faultdetail, int soaperror) +{ return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", NULL, faultstring, faultdetail, soaperror); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +static int +soap_copy_fault(struct soap *soap, const char *faultcode, const char *faultsubcode, const char *faultstring, const char *faultdetail) +{ char *r = NULL, *s = NULL, *t = NULL; + if (faultsubcode) + r = soap_strdup(soap, faultsubcode); + if (faultstring) + s = soap_strdup(soap, faultstring); + if (faultdetail) + t = soap_strdup(soap, faultdetail); + return soap_set_error(soap, faultcode, r, s, t, SOAP_FAULT); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_sender_fault(struct soap *soap, const char *faultstring, const char *faultdetail) +{ return soap_sender_fault_subcode(soap, NULL, faultstring, faultdetail); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_sender_fault_subcode(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail) +{ return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", faultsubcode, faultstring, faultdetail); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_receiver_fault(struct soap *soap, const char *faultstring, const char *faultdetail) +{ return soap_receiver_fault_subcode(soap, NULL, faultstring, faultdetail); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_receiver_fault_subcode(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail) +{ return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", faultsubcode, faultstring, faultdetail); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +#ifndef WITH_NOSTDLIB +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_print_fault(struct soap *soap, FILE *fd) +{ if (soap->error) + { const char *c, *v = NULL, *s, **d; + d = soap_faultcode(soap); + if (!*d) + soap_set_fault(soap); + c = *d; + if (soap->version == 2) + v = *soap_faultsubcode(soap); + s = *soap_faultstring(soap); + d = soap_faultdetail(soap); + fprintf(fd, "%s%d fault: %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, c, v ? v : "no subcode", s ? s : "[no reason]", d && *d ? *d : "[no detail]"); + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +#ifndef WITH_NOSTDLIB +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_print_fault_location(struct soap *soap, FILE *fd) +{ +#ifndef WITH_LEAN + int i, j, c1, c2; + if (soap->error && soap->buflen > 0) + { i = (int)soap->bufidx - 1; + if (i <= 0) + i = 0; + c1 = soap->buf[i]; + soap->buf[i] = '\0'; + if ((int)soap->buflen >= i + 1024) + j = i + 1023; + else + j = (int)soap->buflen - 1; + c2 = soap->buf[j]; + soap->buf[j] = '\0'; + fprintf(fd, "%s%c\n** HERE **\n", soap->buf, c1); + if (soap->bufidx < soap->buflen) + fprintf(fd, "%s\n", soap->buf + soap->bufidx); + soap->buf[i] = c1; + soap->buf[j] = c2; + } +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_register_plugin_arg(struct soap *soap, int (*fcreate)(struct soap*, struct soap_plugin*, void*), void *arg) +{ register struct soap_plugin *p; + register int r; + if (!(p = (struct soap_plugin*)SOAP_MALLOC(soap, sizeof(struct soap_plugin)))) + return soap->error = SOAP_EOM; + p->id = NULL; + p->data = NULL; + p->fcopy = NULL; + p->fdelete = NULL; + r = fcreate(soap, p, arg); + if (!r && p->fdelete) + { p->next = soap->plugins; + soap->plugins = p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Registered '%s' plugin\n", p->id)); + return SOAP_OK; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not register plugin '%s': plugin returned error %d (or fdelete callback not set)\n", p->id?p->id:"?", r)); + SOAP_FREE(soap, p); + return r; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static void * +fplugin(struct soap *soap, const char *id) +{ register struct soap_plugin *p; + for (p = soap->plugins; p; p = p->next) + if (p->id == id || !strcmp(p->id, id)) + return p->data; + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void * +SOAP_FMAC2 +soap_lookup_plugin(struct soap *soap, const char *id) +{ return soap->fplugin(soap, id); +} +#endif + +/******************************************************************************/ +#ifdef __cplusplus +} +#endif + diff --git a/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.6d.h b/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.6d.h new file mode 100644 index 0000000..6047fb6 --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.6d.h @@ -0,0 +1,2075 @@ +/* + +stdsoap2.h 2.7.6d + +gSOAP runtime + +gSOAP XML Web services tools +Copyright (C) 2000-2005, Robert van Engelen, Genivia Inc., All Rights Reserved. +This part of the software is released under one of the following licenses: +GPL, the gSOAP public license, or Genivia's license for commercial use. +-------------------------------------------------------------------------------- +Contributors: + +Wind River Systems, Inc., for the following additions (marked WR[...]): + - vxWorks compatible +-------------------------------------------------------------------------------- +gSOAP public license. + +The contents of this file are subject to the gSOAP Public License Version 1.3 +(the "License"); you may not use this file except in compliance with the +License. You may obtain a copy of the License at +http://www.cs.fsu.edu/~engelen/soaplicense.html +Software distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +for the specific language governing rights and limitations under the License. + +The Initial Developer of the Original Code is Robert A. van Engelen. +Copyright (C) 2000-2005, Robert van Engelen, Genivia Inc., All Rights Reserved. +-------------------------------------------------------------------------------- +GPL license. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA + +Author contact information: +engelen@genivia.com / engelen@acm.org +-------------------------------------------------------------------------------- +A commercial use license is available from Genivia, Inc., contact@genivia.com +-------------------------------------------------------------------------------- +*/ + +#ifdef WITH_SOAPDEFS_H +# include "soapdefs.h" /* include user-defined stuff */ +#endif + +#ifndef _THREAD_SAFE +# define _THREAD_SAFE +#endif + +#ifndef OPENSERVER +# ifndef _REENTRANT +# define _REENTRANT +# endif +#endif + +#ifndef SOAP_FMAC1 /* stdsoap2.h declaration macro */ +# define SOAP_FMAC1 +#endif + +#ifndef SOAP_FMAC2 /* stdsoap2.h declaration macro */ +# define SOAP_FMAC2 +#endif + +#ifndef SOAP_FMAC3 /* (de)serializer declaration macro */ +# define SOAP_FMAC3 +#endif + +#ifndef SOAP_FMAC3S /* string converter for (de)serializer declaration macro */ +# define SOAP_FMAC3S SOAP_FMAC3 +#endif + +#ifndef SOAP_FMAC4 /* (de)serializer declaration macro */ +# define SOAP_FMAC4 +#endif + +#ifndef SOAP_FMAC4S /* string converter for (de)serializer declaration macro */ +# define SOAP_FMAC4S SOAP_FMAC4 +#endif + +#ifndef SOAP_FMAC5 /* stub/skeleton declaration macro */ +# define SOAP_FMAC5 +#endif + +#ifndef SOAP_FMAC6 /* stub/skeleton declaration macro */ +# define SOAP_FMAC6 +#endif + +#ifndef SOAP_CMAC /* class declaration macro */ +# define SOAP_CMAC +#endif + +#ifndef SOAP_NMAC /* namespace table declaration macro */ +# define SOAP_NMAC +#endif + +#ifndef SOAP_SOURCE_STAMP +# define SOAP_SOURCE_STAMP(str) +#endif + +/* gSOAP 2.7.4 and higher: fast look-aside buffering is stable */ +#ifndef WITH_FAST +# define WITH_FAST +#endif + +#ifdef WITH_LEANER +# ifndef WITH_LEAN +# define WITH_LEAN +# endif +#endif + +#ifdef WITH_LEAN +# ifdef WITH_COOKIES +# error "Cannot build WITH_LEAN code WITH_COOKIES enabled" +# endif +#endif + +#ifndef STDSOAP_H +#define STDSOAP_H + +#if defined(__vxworks) || defined(__VXWORKS__) +# define VXWORKS +#endif + +#ifdef _WIN32 +# ifndef WIN32 +# define WIN32 +# endif +#endif + +#ifdef UNDER_CE +# ifndef WIN32 +# define WIN32 +# endif +#endif + +#ifdef __BORLANDC__ +# ifdef __WIN32__ +# ifndef WIN32 +# define WIN32 +# endif +# endif +#endif + +#ifdef __CYGWIN__ +# ifndef CYGWIN +# define CYGWIN +# endif +#endif + +#ifdef __SYMBIAN32__ +# define SYMBIAN +# undef WIN32 +#endif + +#if defined(__palmos__) || defined(PALM_GCC) || defined(__PALMOS_TRAPS__) +# ifndef PALM +# define PALM +# endif +#endif + +#if defined(__hpux) +# ifndef HP_UX +# define HP_UX +# endif +#endif + +#if defined(__alpha) && !defined(__VMS) +# ifndef TRU64 +# define TRU64 +# endif +#endif + +#ifdef __MVS__ +# ifndef OS390 +# define OS390 +# endif +#endif + +#ifdef HAVE_CONFIG_H +# include "config.h" +# ifdef WITH_OPENSSL +# ifndef HAVE_OPENSSL_SSL_H +# undef WITH_OPENSSL +# endif +# endif +#else +# if defined(UNDER_CE) +# define WITH_LEAN +# define HAVE_SSCANF +# elif defined(WIN32) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# define SOAP_LONG_FORMAT "%I64d" +# define SOAP_ULONG_FORMAT "%I64u" +# elif defined(CYGWIN) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(__APPLE__) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_TIMEGM +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(_AIXVERSION_431) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(HP_UX) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(FREEBSD) || defined(__FreeBSD__) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_STRTOLL +# define HAVE_STRTOULL +# define HAVE_GETTIMEOFDAY +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# define SOAP_LONG_FORMAT "%qd" +# define SOAP_ULONG_FORMAT "%qu" +# elif defined(__VMS) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(__GLIBC__) || defined(__GNU__) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_STRTOLL +# define HAVE_STRTOULL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_TIMEGM +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# define HAVE_ISNAN +# elif defined(TRU64) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_STRTOLL +# define HAVE_STRTOULL +# define HAVE_GETTIMEOFDAY +# define HAVE_SYS_TIMEB_H +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define __USE_STD_IOSTREAM +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# define SOAP_LONG_FORMAT "%ld" +# define SOAP_ULONG_FORMAT "%lu" +# elif defined(MAC_CARBON) +# define WITH_NOIO +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GETHOSTBYNAME_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(PALM) +# define WITH_LEAN +# define HAVE_STRTOD /* strtod() is defined in palmFunctions.h */ +# include /* Needs to be included before unix headers */ +# include +# define IGNORE_STDIO_STUBS +# include +# define O_NONBLOCK FNONBIO +# include +# include "palmFunctions.h" +# elif defined(SYMBIAN) +# define WITH_LEAN +# define WITH_NONAMESPACES +# define HAVE_STRTOD /* use STRTOD since sscanf doesn't seem to work */ +# include +# include +# elif defined(VXWORKS) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_PGMTIME_R +# define HAVE_PLOCALTIME_R +# define HAVE_MKTIME +# elif defined(OS390) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(AS400) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# else +/* Default asumptions on supported functions */ +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GETHOSTBYNAME_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# endif +#endif + +/* QNX does not have a working version of strtof */ +#if defined(__QNX__) || defined(QNX) +# undef HAVE_STRTOF +#endif + +#ifndef SOAP_LONG_FORMAT +# define SOAP_LONG_FORMAT "%lld" /* printf format for 64 bit ints */ +#endif + +#ifndef SOAP_ULONG_FORMAT +# define SOAP_ULONG_FORMAT "%llu" /* printf format for unsigned 64 bit ints */ +#endif + +#ifndef WITH_NOSTDLIB +# include +# ifndef PALM +# include +# include +# endif +# include +# include +#endif + +#if defined(__cplusplus) && !defined(WITH_LEAN) +# include +# include +#endif + +#ifdef WITH_NOHTTP +# ifndef WITH_NOIO +# define WITH_NOIO +# undef WITH_COOKIES +# endif +#endif + +#ifndef UNDER_CE +# ifndef PALM +# ifndef WITH_NOIO +# include +# include +# endif +# ifndef WITH_LEAN +# ifdef HAVE_SYS_TIMEB_H +# include /* for ftime() */ +# endif +# include +# endif +# endif +#endif + +#ifdef OPENSERVER +# include +# include +# include + extern int h_errno; +#endif + +#ifndef WITH_NOIO +# ifndef WIN32 +# ifndef PALM +# include +# ifdef VXWORKS +# include +# include +# endif +# ifndef VXWORKS +# ifndef SYMBIAN +# include +# endif +# endif +# ifdef SUN_OS +# include /* SUN */ +# include /* SUN < 2.8 (?) */ +# endif +# ifdef VXWORKS +# ifdef _WRS_KERNEL +# include +# endif +# else +# include +# endif +# include +# ifdef OS390 +# include +# else +# include /* TCP_NODELAY */ +# endif +# include +# endif +# endif +#endif + +#ifdef WITH_FASTCGI +# include +#endif + +#ifdef WITH_OPENSSL +# define OPENSSL_NO_KRB5 +# include +# include +# include +# ifndef ALLOW_OLD_VERSIONS +# if (OPENSSL_VERSION_NUMBER < 0x00905100L) +# error "Must use OpenSSL 0.9.6 or later" +# endif +# endif +#endif + +#ifdef WITH_GZIP +# ifndef WITH_ZLIB +# define WITH_ZLIB +# endif +#endif + +#ifdef WITH_CASEINSENSITIVETAGS +# define SOAP_STRCMP soap_tag_cmp /* case insensitve XML element/attribute names */ +#else +# define SOAP_STRCMP strcmp /* case sensitive XML element/attribute names */ +#endif + +#ifdef WITH_ZLIB +# include +#endif + +#ifndef WITH_NOSTDLIB +# ifndef PALM +# include /* for isnan() */ +# endif +#endif + +/* #define DEBUG */ /* Uncomment to debug sending (in file SENT.log) receiving (in file RECV.log) and messages (in file TEST.log) */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef WIN32 +# ifndef UNDER_CE +# include +# include +# endif +# include +/* # include */ /* Alternative: use winsock2 (not available with eVC) */ +# ifdef WITH_IPV6 +# include +# include +# endif +#else +# ifdef VXWORKS +# include +# include +# include +# endif +# ifndef WITH_NOIO +# ifndef PALM +# include +# include +# include +# include +# endif +# endif +#endif + +/* Portability: define SOAP_SOCKLEN_T */ +#if defined(_AIX) +# define SOAP_SOCKLEN_T socklen_t +#elif defined(SOCKLEN_T) +# define SOAP_SOCKLEN_T SOCKLEN_T +#elif defined(__socklen_t_defined) || defined(_SOCKLEN_T) || defined(CYGWIN) || defined(FREEBSD) || defined(__FreeBSD__) || defined(__QNX__) || defined(QNX) +# define SOAP_SOCKLEN_T socklen_t +#elif defined(IRIX) || defined(WIN32) || defined(__APPLE__) || defined(HP_UX) || defined(SUN_OS) || defined(OPENSERVER) || defined(TRU64) || defined(VXWORKS) +# define SOAP_SOCKLEN_T int +#else +# define SOAP_SOCKLEN_T size_t +#endif + +#ifndef SOAP_SOCKET +# ifdef WIN32 +# define SOAP_SOCKET SOCKET +# else +# define SOAP_SOCKET int +# define closesocket(n) close(n) +# endif +#endif + +#define SOAP_INVALID_SOCKET (-1) +#define soap_valid_socket(n) ((n) != SOAP_INVALID_SOCKET) + +#if defined(SYMBIAN) +# define LONG64 long +# define ULONG64 unsigned LONG64 +#elif !defined(WIN32) || defined(__GLIBC__) || defined(__GNU__) +# ifndef LONG64 +# define LONG64 long long +# define ULONG64 unsigned LONG64 +# endif +#elif defined(UNDER_CE) +# define LONG64 __int64 +# define ULONG64 unsigned LONG64 +#elif defined(__BORLANDC__) +# define LONG64 __int64 +# define ULONG64 unsigned LONG64 +#endif + +#if defined(WIN32) +# define soap_int32 __int32 +#elif defined(SYMBIAN) +# define soap_int32 long +#elif defined(PALM) +# define soap_int32 Int32 +#else +# define soap_int32 int32_t +#endif + +#ifdef WIN32 +# define SOAP_ERANGE ERANGE +# define SOAP_EINTR WSAEINTR +# define SOAP_EAGAIN WSAEWOULDBLOCK +# define SOAP_EWOULDBLOCK WSAEWOULDBLOCK +# define SOAP_EINPROGRESS WSAEINPROGRESS +#else +# define SOAP_ERANGE ERANGE +# define SOAP_EINTR EINTR +# define SOAP_EAGAIN EAGAIN +# ifdef SYMBIAN +# define SOAP_EWOULDBLOCK 9898 +# define SOAP_EINPROGRESS 9899 +# else +# define SOAP_EWOULDBLOCK EWOULDBLOCK +# define SOAP_EINPROGRESS EINPROGRESS +# endif +#endif + +#ifdef WIN32 +# ifdef UNDER_CE +# define soap_errno GetLastError() +# define soap_socket_errno GetLastError() +# define soap_reset_errno SetLastError(0) +# else +# define soap_errno GetLastError() +# define soap_socket_errno WSAGetLastError() +# define soap_reset_errno SetLastError(0) +# endif +#else +# ifndef WITH_NOIO +# define soap_errno errno +# define soap_socket_errno errno +# define soap_reset_errno (errno = 0) +# else +# define soap_errno 0 +# define soap_socket_errno 0 +# define soap_reset_errno +# endif +#endif + +#ifndef SOAP_BUFLEN +# ifdef WITH_UDP +# define SOAP_BUFLEN (65536) /* max UDP packet size */ +# else +# ifndef WITH_LEAN +# define SOAP_BUFLEN (65536) /* buffer length for socket packets, also used by gethostbyname_r so don't make this too small */ +# else +# define SOAP_BUFLEN (2048) +# endif +# endif +#endif +#ifndef SOAP_LABLEN +# define SOAP_LABLEN (64) /* initial look-aside buffer length */ +#endif +#ifndef SOAP_PTRBLK +# define SOAP_PTRBLK (32) /* block allocation for pointer hash table chains */ +#endif +#ifndef SOAP_PTRHASH +# ifndef WITH_LEAN +# define SOAP_PTRHASH (1024) /* size of pointer analysis hash table (must be power of 2) */ +# else +# define SOAP_PTRHASH (32) +# endif +#endif +#ifndef SOAP_IDHASH +# ifndef WITH_LEAN +# define SOAP_IDHASH (1999) /* prime size of hash table for parsed id/ref */ +# else +# define SOAP_IDHASH (19) /* 19, 199 */ +# endif +#endif +#ifndef SOAP_BLKLEN +# ifndef WITH_LEAN +# define SOAP_BLKLEN (256) /* size of blocks to collect long strings and XML attributes */ +# else +# define SOAP_BLKLEN (32) +# endif +#endif +#ifndef SOAP_TAGLEN +# ifndef WITH_LEAN +# define SOAP_TAGLEN (1024) /* maximum length of XML element tag/attribute name or host/path name + 1 */ +# else +# define SOAP_TAGLEN (64) +# endif +#endif +#ifndef SOAP_HDRLEN +# ifndef WITH_LEAN +# define SOAP_HDRLEN (8192) /* maximum length of HTTP header line (must be >4096 to read cookies) */ +# else +# define SOAP_HDRLEN (1024) +# endif +#endif +#ifndef SOAP_MAXDIMS +# ifndef WITH_LEAN +# define SOAP_MAXDIMS (16) /* maximum array dimensions (array nestings) must be less than 64 to protect soap->tmpbuf */ +# else +# define SOAP_MAXDIMS (4) +# endif +#endif + +#ifndef SOAP_MAXLOGS +# define SOAP_MAXLOGS (3) /* max number of debug logs per struct soap environment */ +# define SOAP_INDEX_RECV (0) +# define SOAP_INDEX_SENT (1) +# define SOAP_INDEX_TEST (2) +#endif + +#ifndef SOAP_MAXKEEPALIVE +# define SOAP_MAXKEEPALIVE (100) /* max iterations to keep server connection alive */ +#endif + +#ifndef SOAP_MAXARRAYSIZE +# define SOAP_MAXARRAYSIZE (100000) /* "trusted" max size of inbound SOAP array for compound array allocation */ +#endif + +#ifdef VXWORKS +# ifdef __INCmathh +# include +# ifndef HAVE_ISNAN +# define HAVE_ISNAN +# endif +# define soap_isnan(num) isNan(num) +# endif +#endif + +#ifdef WIN32 +# include +# ifndef HAVE_ISNAN +# define HAVE_ISNAN +# endif +# define soap_isnan(num) _isnan(num) +#endif + +#ifdef SUN_OS +# define soap_isnan(n) isnan(n) +#endif + +#if !defined(HAVE_ISNAN) && (defined(_MATH_H) || defined(_MATH_INCLUDED)) +# define HAVE_ISNAN +#endif + +#ifndef soap_isnan +# ifdef HAVE_ISNAN +# define soap_isnan(n) isnan(n) +# else +# define soap_isnan(_) (0) +# endif +#endif + +extern const struct soap_double_nan { unsigned int n1, n2; } soap_double_nan; + +#ifdef VXWORKS +# ifndef FLT_MAX +# define FLT_MAX _ARCH_FLT_MAX +# endif +# ifndef DBL_MAX +# define DBL_MAX _ARCH_DBL_MAX +# endif +#endif + +#ifndef FLT_NAN +# ifdef HAVE_ISNAN +# define FLT_NAN (*(float*)(void*)&soap_double_nan) +# else +# define FLT_NAN (0.0) +# endif +#endif + +#ifndef FLT_PINFTY +# if defined(FLT_MAX) +# define FLT_PINFTY FLT_MAX +# elif defined(HUGE_VALF) +# define FLT_PINFTY (float)HUGE_VALF +# elif defined(HUGE_VAL) +# define FLT_PINFTY (float)HUGE_VAL +# elif defined(FLOAT_MAX) +# define FLT_PINFTY FLOAT_MAX +# else +# define FLT_PINFTY (3.40282347e+38F) +# endif +#endif + +#ifndef FLT_NINFTY +# define FLT_NINFTY (-FLT_PINFTY) +#endif + +#ifndef DBL_NAN +# ifdef HAVE_ISNAN +# define DBL_NAN (*(double*)(void*)&soap_double_nan) +# else +# define DBL_NAN (0.0) +# endif +#endif + +#ifndef DBL_PINFTY +# if defined(DBL_MAX) +# define DBL_PINFTY DBL_MAX +# elif defined(HUGE_VALF) +# define DBL_PINFTY (double)HUGE_VALF +# elif defined(HUGE_VAL) +# define DBL_PINFTY (double)HUGE_VAL +# elif defined(DOUBLE_MAX) +# define DBL_PINFTY DOUBLE_MAX +# else +# define DBL_PINFTY (1.7976931348623157e+308) +# endif +#endif + +#ifndef DBL_NINFTY +# define DBL_NINFTY (-DBL_PINFTY) +#endif + +#define soap_ispinfd(n) ((n) >= DBL_PINFTY) +#define soap_ispinff(n) ((n) >= FLT_PINFTY) +#define soap_isninfd(n) ((n) <= DBL_NINFTY) +#define soap_isninff(n) ((n) <= FLT_NINFTY) + +/* gSOAP error codes */ + +#define SOAP_EOF EOF +#define SOAP_ERR EOF +#define SOAP_OK 0 +#define SOAP_CLI_FAULT 1 +#define SOAP_SVR_FAULT 2 +#define SOAP_TAG_MISMATCH 3 +#define SOAP_TYPE 4 +#define SOAP_SYNTAX_ERROR 5 +#define SOAP_NO_TAG 6 +#define SOAP_IOB 7 +#define SOAP_MUSTUNDERSTAND 8 +#define SOAP_NAMESPACE 9 +#define SOAP_USER_ERROR 10 +#define SOAP_FATAL_ERROR 11 +#define SOAP_FAULT 12 +#define SOAP_NO_METHOD 13 +#define SOAP_GET_METHOD 14 +#define SOAP_EOM 15 +#define SOAP_NULL 16 +#define SOAP_DUPLICATE_ID 17 +#define SOAP_MISSING_ID 18 +#define SOAP_HREF 19 +#define SOAP_UDP_ERROR 20 +#define SOAP_TCP_ERROR 21 +#define SOAP_HTTP_ERROR 22 +#define SOAP_SSL_ERROR 23 +#define SOAP_ZLIB_ERROR 24 +#define SOAP_DIME_ERROR 25 +#define SOAP_DIME_HREF 26 +#define SOAP_DIME_MISMATCH 27 +#define SOAP_DIME_END 28 +#define SOAP_MIME_ERROR 29 +#define SOAP_MIME_HREF 30 +#define SOAP_MIME_END 31 +#define SOAP_VERSIONMISMATCH 32 +#define SOAP_PLUGIN_ERROR 33 +#define SOAP_DATAENCODINGUNKNOWN 34 +#define SOAP_REQUIRED 35 +#define SOAP_PROHIBITED 36 +#define SOAP_OCCURS 37 +#define SOAP_LENGTH 38 + +#define soap_xml_error_check(e) ((e) == SOAP_TAG_MISMATCH || (e) == SOAP_TAG_END || (e) == SOAP_SYNTAX_ERROR || (e) == SOAP_NAMESPACE || (e) == SOAP_DUPLICATE_ID || (e) == SOAP_MISSING_ID || (e) == SOAP_REQUIRED || (e) == SOAP_PROHIBITED || (e) == SOAP_OCCURS || (e) == SOAP_LENGTH || (e) == SOAP_NULL || (e) == SOAP_HREF) +#define soap_soap_error_check(e) ((e) == SOAP_CLI_FAULT || (e) == SOAP_SVR_FAULT || (e) == SOAP_VERSIONMISMATCH || (e) == SOAP_MUSTUNDERSTAND || (e) == SOAP_FAULT || (e) == SOAP_NO_METHOD) +#define soap_tcp_error_check(e) ((e) == SOAP_EOF || (e) == SOAP_TCP_ERROR) +#define soap_ssl_error_check(e) ((e) == SOAP_SSL_ERROR) +#define soap_zlib_error_check(e) ((e) == SOAP_ZLIB_ERROR) +#define soap_http_error_check(e) ((e) == SOAP_HTTP_ERROR || (e) == SOAP_GET_METHOD || ((e) >= 100 && (e) < 600)) + +/* gSOAP HTTP response status codes 100 to 599 are reserved */ + +/* Codes 600 to 999 are user definable */ + +/* Exceptional gSOAP HTTP response status codes >= 1000 */ + +#define SOAP_STOP 1000 /* No HTTP response */ +#define SOAP_FORM 1001 /* Form request/response */ +#define SOAP_HTML 1002 /* Custom HTML response */ +#define SOAP_FILE 1003 /* Custom file-based response */ + +/* gSOAP HTTP method codes */ + +#define SOAP_POST 2000 +#define SOAP_GET 2001 + +/* gSOAP DIME */ + +#define SOAP_DIME_CF 0x01 +#define SOAP_DIME_ME 0x02 +#define SOAP_DIME_MB 0x04 +#define SOAP_DIME_VERSION 0x08 /* DIME version 1 */ +#define SOAP_DIME_MEDIA 0x10 +#define SOAP_DIME_ABSURI 0x20 + +/* gSOAP ZLIB */ + +#define SOAP_ZLIB_NONE 0x00 +#define SOAP_ZLIB_DEFLATE 0x01 +#define SOAP_ZLIB_INFLATE 0x02 +#define SOAP_ZLIB_GZIP 0x02 + +/* gSOAP transport, connection, and content encoding modes */ + +typedef soap_int32 soap_mode; + +#define SOAP_IO 0x00000003 /* IO mask */ +#define SOAP_IO_FLUSH 0x00000000 /* flush output immediately, no buffering */ +#define SOAP_IO_BUFFER 0x00000001 /* buffer output in packets of size SOAP_BUFLEN */ +#define SOAP_IO_STORE 0x00000002 /* store entire output to determine length for transport */ +#define SOAP_IO_CHUNK 0x00000003 /* use HTTP chunked transfer AND buffer packets */ + +#define SOAP_IO_UDP 0x00000004 +#define SOAP_IO_LENGTH 0x00000008 +#define SOAP_IO_KEEPALIVE 0x00000010 + +#define SOAP_ENC_LATIN 0x00800020 /* iso-8859-1 encoding */ +#define SOAP_ENC_XML 0x00000040 /* plain XML encoding, no HTTP header */ +#define SOAP_ENC_DIME 0x00000080 +#define SOAP_ENC_MIME 0x00000100 +#define SOAP_ENC_MTOM 0x00000200 +#define SOAP_ENC_ZLIB 0x00000400 +#define SOAP_ENC_SSL 0x00000800 + +#define SOAP_ENC 0x00000FFF /* IO and ENC mask */ + +#define SOAP_XML_STRICT 0x00001000 /* strict validation */ +#define SOAP_XML_INDENT 0x00002000 +#define SOAP_XML_CANONICAL 0x00004000 /* EXC C14N canonical XML */ +#define SOAP_XML_TREE 0x00008000 +#define SOAP_XML_GRAPH 0x00010000 +#define SOAP_XML_NIL 0x00020000 +#define SOAP_XML_DOM 0x00040000 +#define SOAP_XML_SEC 0x00080000 /* reserved for WS security */ + +#define SOAP_C_NOIOB 0x00100000 +#define SOAP_C_UTFSTRING 0x00200000 +#define SOAP_C_MBSTRING 0x00400000 + +#define SOAP_DOM_TREE 0x01000000 +#define SOAP_DOM_NODE 0x02000000 +#define SOAP_DOM_ASIS 0x04000000 + +#define SOAP_IO_DEFAULT SOAP_IO_FLUSH + +/* SSL client/server authentication settings */ + +#define SOAP_SSL_NO_AUTHENTICATION 0x00 /* for testing purposes */ +#define SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION 0x01 /* client requires server to authenticate */ +#define SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION 0x02 /* server requires client to authenticate */ + +#define SOAP_SSL_DEFAULT SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION + +/* */ + +#define SOAP_BEGIN 0 +#define SOAP_IN_ENVELOPE 2 +#define SOAP_IN_HEADER 3 +#define SOAP_END_HEADER 4 +#define SOAP_NO_BODY 5 +#define SOAP_IN_BODY 6 +#define SOAP_END_BODY 7 +#define SOAP_END_ENVELOPE 8 +#define SOAP_END 9 +#define SOAP_BEGIN_SECURITY 10 +#define SOAP_IN_SECURITY 11 +#define SOAP_END_SECURITY 12 + +/* DEBUG macros */ + +#ifndef WITH_LEAN +# ifdef DEBUG +# ifndef SOAP_DEBUG +# define SOAP_DEBUG +# endif +# endif +#endif + +#ifdef SOAP_DEBUG +# define SOAP_MALLOC(soap, size) soap_track_malloc(soap, __FILE__, __LINE__, size) +# define SOAP_FREE(soap, ptr) soap_track_free(soap, __FILE__, __LINE__, ptr) +#endif + +#ifndef SOAP_MALLOC /* use libc malloc */ +# define SOAP_MALLOC(soap, size) malloc(size) +#endif + +#ifndef SOAP_FREE /* use libc free */ +# define SOAP_FREE(soap, ptr) free(ptr) +#endif + +#ifdef SOAP_DEBUG +# ifndef SOAP_MESSAGE +# define SOAP_MESSAGE fprintf +# endif +# ifndef DBGLOG +# define DBGLOG(DBGFILE, CMD) \ +{ if (soap)\ + { if (!soap->fdebug[SOAP_INDEX_##DBGFILE])\ + soap_open_logfile(soap, SOAP_INDEX_##DBGFILE);\ + if (soap->fdebug[SOAP_INDEX_##DBGFILE])\ + { FILE *fdebug = soap->fdebug[SOAP_INDEX_##DBGFILE];\ + CMD;\ + fflush(fdebug);\ + }\ + }\ +} +# endif +# ifndef DBGMSG +# define DBGMSG(DBGFILE, MSG, LEN) \ +{ if (soap)\ + { if (!soap->fdebug[SOAP_INDEX_##DBGFILE])\ + soap_open_logfile(soap, SOAP_INDEX_##DBGFILE);\ + if (soap->fdebug[SOAP_INDEX_##DBGFILE])\ + { fwrite((MSG), 1, (LEN), soap->fdebug[SOAP_INDEX_##DBGFILE]);\ + fflush(soap->fdebug[SOAP_INDEX_##DBGFILE]);\ + }\ + }\ +} +# endif +# ifndef DGBFUN +# define DBGFUN(FNAME) DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): %s()\n", __FILE__, __LINE__, FNAME)) +# define DBGFUN1(FNAME, FMT, ARG) DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): %s("FMT")\n", __FILE__, __LINE__, FNAME, (ARG))) +# define DBGFUN2(FNAME, FMT1, ARG1, FMT2, ARG2) DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): %s("FMT1", "FMT2")\n", __FILE__, __LINE__, FNAME, (ARG1), (ARG2))) +# define DBGFUN3(FNAME, FMT1, ARG1, FMT2, ARG2, FMT3, ARG3) DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): %s("FMT1", "FMT2", "FMT3")\n", __FILE__, __LINE__, FNAME, (ARG1), (ARG2), (ARG3))) +# endif +# ifndef DBGHEX +# define DBGHEX(DBGFILE, MSG, LEN) \ +{ if (soap)\ + { if (!soap->fdebug[SOAP_INDEX_##DBGFILE])\ + soap_open_logfile(soap, SOAP_INDEX_##DBGFILE);\ + if (soap->fdebug[SOAP_INDEX_##DBGFILE])\ + { int i; char *s;\ + for (s = (char*)(MSG), i = (LEN); i; i--)\ + fprintf(soap->fdebug[SOAP_INDEX_##DBGFILE], "%2.2hhX ", *s++);\ + fflush(soap->fdebug[SOAP_INDEX_##DBGFILE]);\ + }\ + }\ +} +# endif +#else +# define DBGLOG(DBGFILE, CMD) +# define DBGMSG(DBGFILE, MSG, LEN) +# define DBGFUN(FNAME) +# define DBGFUN1(FNAME, FMT, ARG) +# define DBGFUN2(FNAME, FMT1, ARG1, FMT2, ARG2) +# define DBGFUN3(FNAME, FMT1, ARG1, FMT2, ARG2, FMT3, ARG3) +# define DBGHEX(DBGFILE, MSG, LEN) +#endif + +/* UCS-4 requires 32 bits (0-7FFFFFFF, the sign bit is used by gSOAP to distinguish XML entities) */ +typedef soap_int32 soap_wchar; + +/* namespace table row */ +struct Namespace +{ const char *id; + const char *ns; + const char *in; + char *out; +}; + +/* namespace stack */ +struct soap_nlist +{ struct soap_nlist *next; + unsigned int level; /* nesting depth level */ + short index; /* corresponding entry in ns mapping table */ + char *ns; /* only set when parsed ns URI is not in the ns mapping table */ + char id[1]; /* the actual string value flows into the allocated region below this struct */ +}; + +/* block stack for nested block allocations */ +struct soap_blist +{ struct soap_blist *next; + char *ptr; + size_t size; +}; + +/* array layout */ +struct soap_array +{ void *__ptr; + int __size; +}; + +/* pointer serialization management */ +struct soap_plist +{ struct soap_plist *next; + const void *ptr; + const struct soap_array *array; + int type; + int id; + char mark1; + char mark2; +}; + +/* block allocation for pointer serialization management */ +struct soap_pblk +{ struct soap_pblk *next; + struct soap_plist plist[SOAP_PTRBLK]; +}; + +#ifdef SOAP_DEBUG +/* malloc/free tracking for debugging */ +struct soap_mlist +{ struct soap_mlist *next; + const void *ptr; + const char *file; + int line; + short live; +}; +#endif + +/* class allocation list */ +struct soap_clist +{ struct soap_clist *next; + void *ptr; + int type; + int size; + void (*fdelete)(struct soap_clist*); +}; + +/* attributes */ +struct soap_attribute +{ struct soap_attribute *next; + char *value; + size_t size; + char *ns; + short visible; + char name[1]; /* the actual name string flows into the allocated region below this struct */ +}; + +struct soap_cookie +{ struct soap_cookie *next; + char *name; + char *value; + char *domain; + char *path; + long expire; /* client-side: local time to expire; server-side: seconds to expire */ + unsigned int version; + short secure; + short session; /* server-side */ + short env; /* server-side: got cookie from client and should not be (re)send */ + short modified; /* server-side: client cookie was modified and should be send */ +}; + +#ifdef __cplusplus +SOAP_FMAC1 struct soap_multipart* SOAP_FMAC2 soap_next_multipart(struct soap_multipart*); + +class soap_multipart_iterator +{ public: + struct soap_multipart *content; + bool operator==(const soap_multipart_iterator& iter) const + { return content == iter.content; } + bool operator!=(const soap_multipart_iterator& iter) const + { return content != iter.content; } + struct soap_multipart &operator*() const + { return *content; } + soap_multipart_iterator &operator++() + { content = soap_next_multipart(content); return *this; } + soap_multipart_iterator() : content(NULL) + { } + soap_multipart_iterator(struct soap_multipart *p) : content(p) + { } +}; +#endif + +#ifndef WITH_LEANER +struct soap_dime +{ size_t count; + size_t size; + size_t chunksize; + size_t buflen; + char flags; + char *ptr; + const char *id; + const char *type; + const char *options; + struct soap_multipart *list; /* list of DIME attachments received */ + struct soap_multipart *first, *last; /* temporary in/out queue */ +#ifdef __cplusplus + soap_multipart_iterator begin() + { soap_multipart_iterator iter(list); return iter; }; + soap_multipart_iterator end() + { soap_multipart_iterator iter(NULL); return iter; }; +#endif +}; +#endif + +#ifndef WITH_LEANER +struct soap_mime +{ char *boundary; /* MIME boundary */ + const char *start; /* MIME start ID */ + struct soap_multipart *list; /* list of MIME attachments received */ + struct soap_multipart *first, *last; /* temporary in/out queue */ +#ifdef __cplusplus + soap_multipart_iterator begin() + { soap_multipart_iterator iter(list); return iter; }; + soap_multipart_iterator end() + { soap_multipart_iterator iter(NULL); return iter; }; +#endif +}; +#endif + +#ifndef WITH_LEANER +/* RFC2045 MIME content transfer encodings */ +enum soap_mime_encoding +{ SOAP_MIME_NONE, + SOAP_MIME_7BIT, + SOAP_MIME_8BIT, + SOAP_MIME_BINARY, + SOAP_MIME_QUOTED_PRINTABLE, + SOAP_MIME_BASE64, + SOAP_MIME_IETF_TOKEN, + SOAP_MIME_X_TOKEN +}; +#endif + +#ifndef WITH_LEANER +/* DIME/MIME multipart list */ +struct soap_multipart +{ struct soap_multipart *next; + char *ptr; /* points to raw data content */ + size_t size; /* size of data content */ + const char *id; /* DIME/MIME content ID or form data name */ + const char *type; /* DIME/MIME type (MIME type format) */ + const char *options; /* DIME options */ + enum soap_mime_encoding encoding; /* MIME Content-Transfer-Encoding */ + const char *location; /* MIME Content-Location (optional) */ + const char *description; /* MIME Content-Description (optional) */ +#ifdef __cplusplus + typedef soap_multipart_iterator iterator; +#endif +}; +#endif + +#ifndef WITH_LEANER +/* attachment DIME and MTOM XOP forwarding */ +struct soap_xlist +{ struct soap_xlist *next; + unsigned char **ptr; + int *size; + char *id; + char **type; + char **options; +}; +#endif + +/******************************************************************************/ + +#ifndef WITH_LEANER +#ifdef __cplusplus +class soap_dom_attribute_iterator +{ public: + struct soap_dom_attribute *att; + const char *nstr; + const char *name; + bool operator==(const soap_dom_attribute_iterator&) const; + bool operator!=(const soap_dom_attribute_iterator&) const; + struct soap_dom_attribute &operator*() const; + soap_dom_attribute_iterator &operator++(); + soap_dom_attribute_iterator(); + soap_dom_attribute_iterator(struct soap_dom_attribute*); + ~soap_dom_attribute_iterator(); +}; +#endif +#endif + +#ifndef WITH_LEANER +struct soap_dom_attribute +{ struct soap_dom_attribute *next; + const char *nstr; + char *name; + char *data; + wchar_t *wide; + struct soap *soap; +#ifdef __cplusplus + typedef soap_dom_attribute_iterator iterator; + struct soap_dom_attribute &set(const char *nstr, const char *name); /* set namespace and name */ + struct soap_dom_attribute &set(const char *data); /* set data */ + soap_dom_attribute_iterator begin(); + soap_dom_attribute_iterator end(); + soap_dom_attribute_iterator find(const char *nstr, const char *name); + void unlink(); + soap_dom_attribute(); + soap_dom_attribute(struct soap *soap); + soap_dom_attribute(struct soap *soap, const char *nstr, const char *name, const char *data); + ~soap_dom_attribute(); +#endif +}; +#endif + +#ifndef WITH_LEANER +#ifdef __cplusplus +class soap_dom_element_iterator +{ public: + struct soap_dom_element *elt; + const char *nstr; + const char *name; + int type; + bool operator==(const soap_dom_element_iterator&) const; + bool operator!=(const soap_dom_element_iterator&) const; + struct soap_dom_element &operator*() const; + soap_dom_element_iterator &operator++(); + soap_dom_element_iterator(); + soap_dom_element_iterator(struct soap_dom_element*); + ~soap_dom_element_iterator(); +}; +#endif +#endif + +#ifndef WITH_LEANER +struct soap_dom_element +{ struct soap_dom_element *next; /* next sibling */ + struct soap_dom_element *prnt; /* parent */ + struct soap_dom_element *elts; /* list of child elements */ + struct soap_dom_attribute *atts; /* list of attributes */ + const char *nstr; /* namespace string */ + char *name; /* element tag name */ + char *data; /* element content data (with SOAP_C_UTFSTRING flag set) */ + wchar_t *wide; /* element content data */ + int type; /* optional: serialized C/C++ data type */ + void *node; /* optional: pointer to serialized C/C++ data */ + char *head; /* leading whitespace to start tag */ + char *tail; /* leading whitespace to end tag */ + struct soap *soap; /* soap context that manages this node */ +#ifdef __cplusplus + typedef soap_dom_element_iterator iterator; + struct soap_dom_element &set(const char *nstr, const char *name); + struct soap_dom_element &set(const char *data); + struct soap_dom_element &set(void *node, int type); + struct soap_dom_element &add(struct soap_dom_element*); + struct soap_dom_element &add(struct soap_dom_element&); + struct soap_dom_element &add(struct soap_dom_attribute*); + struct soap_dom_element &add(struct soap_dom_attribute&); + soap_dom_element_iterator begin(); + soap_dom_element_iterator end(); + soap_dom_element_iterator find(const char *nstr, const char *name); + soap_dom_element_iterator find(int type); + void unlink(); + soap_dom_element(); + soap_dom_element(struct soap *soap); + soap_dom_element(struct soap *soap, const char *nstr, const char *name); + soap_dom_element(struct soap *soap, const char *nstr, const char *name, const char *data); + soap_dom_element(struct soap *soap, const char *nstr, const char *name, void *node, int type); + ~soap_dom_element(); +#endif +}; +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_dom_next_element(struct soap_dom_element *elt); +SOAP_FMAC1 struct soap_dom_attribute * SOAP_FMAC2 soap_dom_next_attribute(struct soap_dom_attribute *att); +#endif + +#if defined(__cplusplus) && !defined(WITH_LEAN) +} +extern std::ostream &operator<<(std::ostream&, const struct soap_dom_element&); +extern std::istream &operator>>(std::istream&, struct soap_dom_element&); +extern "C" { +#endif + +/******************************************************************************/ + +struct soap +{ short version; /* 1 = SOAP1.1 and 2 = SOAP1.2 (set automatically from namespace URI in nsmap table) */ + short copy; /* 1 = copy of another soap struct */ + soap_mode mode; + soap_mode imode; + soap_mode omode; + const char *float_format; /* user-definable format string for floats (<1024 chars) */ + const char *double_format; /* user-definable format string for doubles (<1024 chars) */ + const char *dime_id_format; /* user-definable format string for integer DIME id ( 0, gives socket recv timeout in seconds, < 0 in usec */ + int send_timeout; /* when > 0, gives socket send timeout in seconds, < 0 in usec */ + int connect_timeout; /* when > 0, gives socket connect() timeout in seconds, < 0 in usec */ + int accept_timeout; /* when > 0, gives socket accept() timeout in seconds, < 0 in usec */ + int socket_flags; /* socket recv() and send() flags, e.g. set to MSG_NOSIGNAL to disable sigpipe */ + int connect_flags; /* connect() SOL_SOCKET sockopt flags, e.g. set to SO_DEBUG to debug socket */ + int bind_flags; /* bind() SOL_SOCKET sockopt flags, e.g. set to SO_REUSEADDR to enable reuse */ + int accept_flags; /* accept() SOL_SOCKET sockopt flags */ + const struct Namespace *namespaces; /* Pointer to global namespace mapping table */ + struct Namespace *local_namespaces; /* Local namespace mapping table */ + struct soap_nlist *nlist; /* namespace stack */ + struct soap_blist *blist; /* block allocation stack */ + struct soap_clist *clist; /* class instance allocation list */ + void *alist; /* memory allocation (malloc) list */ + struct soap_ilist *iht[SOAP_IDHASH]; + struct soap_plist *pht[SOAP_PTRHASH]; + struct soap_pblk *pblk; /* plist block allocation */ + short pidx; /* plist block allocation */ + struct SOAP_ENV__Header *header; + struct SOAP_ENV__Fault *fault; + int idnum; + void *user; /* to pass user-defined data */ + struct soap_plugin *plugins; /* linked list of plug-in data */ + char *userid; /* HTTP Basic authorization userid */ + char *passwd; /* HTTP Basic authorization passwd */ + int (*fpost)(struct soap*, const char*, const char*, int, const char*, const char*, size_t); + int (*fget)(struct soap*); + int (*fform)(struct soap*); + int (*fposthdr)(struct soap*, const char*, const char*); + int (*fresponse)(struct soap*, int, size_t); + int (*fparse)(struct soap*); + int (*fparsehdr)(struct soap*, const char*, const char*); + int (*fresolve)(struct soap*, const char*, struct in_addr* inaddr); + int (*fconnect)(struct soap*, const char*, const char*, int); + int (*fdisconnect)(struct soap*); + int (*fclosesocket)(struct soap*, SOAP_SOCKET); + int (*fshutdownsocket)(struct soap*, SOAP_SOCKET, int); + int (*fopen)(struct soap*, const char*, const char*, int); + int (*faccept)(struct soap*, int, struct sockaddr*, int *n); + int (*fclose)(struct soap*); + int (*fsend)(struct soap*, const char*, size_t); + size_t (*frecv)(struct soap*, char*, size_t); + int (*fpoll)(struct soap*); + void (*fseterror)(struct soap*, const char **c, const char **s); + int (*fignore)(struct soap*, const char*); + int (*fserveloop)(struct soap*); + void *(*fplugin)(struct soap*, const char*); +#ifndef WITH_LEANER + int (*fprepareinit)(struct soap*); + int (*fpreparesend)(struct soap*, const char*, size_t); + int (*fpreparerecv)(struct soap*, const char*, size_t); + int (*fpreparefinal)(struct soap*); + void *(*fdimereadopen)(struct soap*, void*, const char*, const char*, const char*); + void *(*fdimewriteopen)(struct soap*, const char*, const char*, const char*); + void (*fdimereadclose)(struct soap*, void*); + void (*fdimewriteclose)(struct soap*, void*); + size_t (*fdimeread)(struct soap*, void*, char*, size_t); + int (*fdimewrite)(struct soap*, void*, const char*, size_t); +#endif + int master; + int socket; +#if defined(__cplusplus) && !defined(WITH_LEAN) + std::ostream *os; + std::istream *is; +#else + void *os; /* preserve alignment */ + void *is; /* preserve alignment */ +#endif +#ifndef UNDER_CE + int sendfd; + int recvfd; +#else + FILE *sendfd; + FILE *recvfd; +#endif +#ifdef WIN32 + char errorstr[256]; /* buf for FormatMessage() */ +#endif + size_t bufidx; /* index in soap.buf[] */ + size_t buflen; /* length of soap.buf[] content */ + soap_wchar ahead; /* parser lookahead */ + short cdata; /* CDATA parser state */ + short body; /* parsed XML element has a body or not */ + unsigned int level; /* XML nesting level */ + size_t count; /* message length counter */ + size_t length; /* message length as set by HTTP header */ +#ifdef WITH_FAST + char *labbuf; /* look-aside buffer */ + size_t lablen; /* look-aside buffer allocated length */ + size_t labidx; /* look-aside buffer index to available part */ +#endif + char buf[SOAP_BUFLEN];/* send and receive buffer */ + char tmpbuf[1024]; /* in/output buffer for HTTP headers, simpleType values, attribute names, and DIME >=1024 bytes */ + char msgbuf[1024]; /* output buffer for (error) messages <=1024 bytes */ + char tag[SOAP_TAGLEN]; + char id[SOAP_TAGLEN]; + char href[SOAP_TAGLEN]; + char type[SOAP_TAGLEN]; + char arrayType[SOAP_TAGLEN]; + char arraySize[SOAP_TAGLEN]; + char arrayOffset[SOAP_TAGLEN]; + short other; + short position; + int positions[SOAP_MAXDIMS]; + short root; + struct soap_attribute *attributes; /* attribute list */ + short encoding; /* when set, output encodingStyle */ + short mustUnderstand; /* a mustUnderstand element was parsed or is output */ + short keep_alive; /* connection should be kept open */ + short null; /* parsed XML is xsi:nil */ + short ns; /* when not set, output full xmlns bindings */ + short part; /* parsing state */ + short alloced; + short peeked; + size_t chunksize; + size_t chunkbuflen; + char endpoint[SOAP_TAGLEN]; + char path[SOAP_TAGLEN]; + char host[SOAP_TAGLEN]; + char *action; + char *authrealm; /* HTTP authentication realm */ + char *prolog; /* XML declaration prolog */ + unsigned long ip; /* IP number */ + int port; /* port number */ + unsigned int max_keep_alive; + const char *proxy_host; /* Proxy Server host name */ + int proxy_port; /* Proxy Server port (default = 8080) */ + const char *proxy_userid; /* Proxy Authorization user name */ + const char *proxy_passwd; /* Proxy Authorization password */ + int status; /* -1 when request, else error code to be returned by server */ + int error; + int errmode; + int errnum; +#ifndef WITH_LEANER + struct soap_dom_element *dom; + struct soap_dime dime; + struct soap_mime mime; + struct soap_xlist *xlist; +#endif +#if !defined(WITH_LEAN) || defined(SOAP_DEBUG) + const char *logfile[SOAP_MAXLOGS]; + FILE *fdebug[SOAP_MAXLOGS]; + struct soap_mlist *mht[SOAP_PTRHASH]; +#endif +#ifndef WITH_LEAN + const char *c14ninclude; + const char *c14nexclude; + struct soap_cookie *cookies; + const char *cookie_domain; + const char *cookie_path; + int cookie_max; +#endif +#ifndef WITH_NOIO +#ifdef WITH_IPV6 + struct sockaddr_storage peer; /* IPv6: set by soap_accept and by UDP recv */ +#else + struct sockaddr_in peer; /* IPv4: set by soap_connect/soap_accept and by UDP recv */ +#endif + size_t peerlen; +#endif +#ifdef WITH_OPENSSL + int (*fsslauth)(struct soap*); + int (*fsslverify)(int, X509_STORE_CTX*); + BIO *bio; + SSL *ssl; + SSL_CTX *ctx; + short require_server_auth; + short require_client_auth; + short rsa; /* when set, use RSA instead of DH */ + const char *keyfile; + const char *password; + const char *dhfile; + const char *cafile; + const char *capath; + const char *crlfile; + const char *randfile; + SSL_SESSION *session; + char session_host[SOAP_TAGLEN]; + int session_port; +#endif +#ifdef WITH_ZLIB + short zlib_state; /* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_INFLATE */ + short zlib_in; /* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_GZIP */ + short zlib_out; /* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_GZIP */ + z_stream d_stream; /* decompression stream */ + char z_buf[SOAP_BUFLEN]; /* buffer */ + size_t z_buflen; + unsigned short z_level; /* compression level to be used (0=none, 1=fast to 9=best) */ + uLong z_crc; /* internal gzip crc */ + float z_ratio_in; /* detected compression ratio compressed_length/length of inbound message */ + float z_ratio_out; /* detected compression ratio compressed_length/length of outbound message */ +#endif +#ifdef WMW_RPM_IO + void *rpmreqid; +#endif +}; + +struct soap_code_map +{ long code; + const char *string; +}; + +/* forwarding list */ +struct soap_flist +{ struct soap_flist *next; + int type; + void *ptr; + unsigned int level; + void (*fcopy)(struct soap*, int, int, void*, const void*, size_t); +}; + +/* id-ref forwarding list */ +struct soap_ilist +{ struct soap_ilist *next; + int type; + size_t size; + void *link; + void *copy; + struct soap_flist *flist; + void *ptr; + unsigned int level; + char id[1]; /* the actual id string value flows into the allocated region below this struct */ +}; + +struct soap_plugin +{ struct soap_plugin *next; + const char *id; + void *data; + int (*fcopy)(struct soap *soap, struct soap_plugin *dst, struct soap_plugin *src); + void (*fdelete)(struct soap *soap, struct soap_plugin *p); /* should delete fields of plugin only and not free(p) */ +}; + +#ifndef WITH_NONAMESPACES +extern SOAP_NMAC struct Namespace namespaces[]; +#endif + +#ifndef WITH_LEAN +# define soap_get0(soap) (((soap)->bufidx>=(soap)->buflen && soap_recv(soap)) ? EOF : (unsigned char)(soap)->buf[(soap)->bufidx]) +# define soap_get1(soap) (((soap)->bufidx>=(soap)->buflen && soap_recv(soap)) ? EOF : (unsigned char)(soap)->buf[(soap)->bufidx++]) +#else +soap_wchar soap_get0(struct soap*); +soap_wchar soap_get1(struct soap*); +#endif + +#define soap_revget1(soap) ((soap)->bufidx--) +#define soap_unget(soap, c) ((soap)->ahead = c) +#define soap_register_plugin(soap, plugin) soap_register_plugin_arg(soap, plugin, NULL) +#define soap_imode(soap, n) ((soap)->mode = (soap)->imode = (n)) +#define soap_set_imode(soap, n) ((soap)->imode |= (n)) +#define soap_clr_imode(soap, n) ((soap)->imode &= ~(n)) +#define soap_omode(soap, n) ((soap)->mode = (soap)->omode = (n)) +#define soap_set_omode(soap, n) ((soap)->omode |= (n)) +#define soap_clr_omode(soap, n) ((soap)->omode &= ~(n)) +#define soap_set_mode(soap, n) ((soap)->imode |= (n), (soap)->omode |= (n)) +#define soap_clr_mode(soap, n) ((soap)->imode &= ~(n), (soap)->omode &= ~(n)) +#define soap_destroy(soap) soap_delete((soap), NULL) + +#ifdef HAVE_STRRCHR +# define soap_strrchr(s, t) strrchr(s, t) +#else + SOAP_FMAC1 char* SOAP_FMAC2 soap_strrchr(const char *s, int t); +#endif + +#ifdef HAVE_STRTOL +# define soap_strtol(s, t, b) strtol(s, t, b) +#else + SOAP_FMAC1 long SOAP_FMAC2 soap_strtol(const char *s, char **t, int b); +#endif + +#ifdef HAVE_STRTOUL +# define soap_strtoul(s, t, b) strtoul(s, t, b) +#else + SOAP_FMAC1 unsigned long SOAP_FMAC2 soap_strtoul(const char *s, char **t, int b); +#endif + +#if defined(WITH_OPENSSL) +# define soap_random soap_rand() +SOAP_FMAC1 int SOAP_FMAC2 soap_rand(); +#elif defined(HAVE_RANDOM) +# define soap_random (int)random() +#else +# define soap_random rand() +#endif + +#ifdef WITH_NOIDREF +# define soap_embedded(s, p, t) (0) +# define soap_id_lookup(s, i, p, t, n, k) (p) +# define soap_id_forward(s, h, p, st, tt, n, k, fc) (p) +# define soap_reference(s, a, t) (1) +# define soap_array_reference(s, p, a, n, t) (1) +# define soap_embed(s, p, a, n, t, pp) (0) +# define soap_embedded_id(s, i, p, t) (i) +# define soap_is_embedded(s, p) (0) +# define soap_is_single(s, p) (1) +# define soap_lookup_type(s, i) (0) +# define soap_getindependent(s) (0) +# define soap_putindependent(s) (0) +# define soap_getelement(s, n) (n) +# define soap_putelement(s, p, t, i, n) (0) +# define soap_markelement(s, p, n) (0) +#endif + +SOAP_FMAC1 void SOAP_FMAC2 soap_fault(struct soap*); +SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultcode(struct soap*); +SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultsubcode(struct soap*); +SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultstring(struct soap*); +SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultdetail(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_serializeheader(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putheader(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getheader(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_serializefault(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putfault(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getfault(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_poll(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_connect_command(struct soap*, int, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_connect(struct soap*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_bind(struct soap*, const char*, int, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_accept(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_accept(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_server_context(struct soap*, unsigned short, const char*, const char*, const char*, const char*, const char*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_client_context(struct soap*, unsigned short, const char*, const char*, const char*, const char*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_puthttphdr(struct soap*, int status, size_t count); + +SOAP_FMAC1 const char* SOAP_FMAC2 soap_get_header_attribute(struct soap*, const char*, const char*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_decode_key(char*, size_t, const char*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_decode_val(char*, size_t, const char*); + +SOAP_FMAC1 size_t SOAP_FMAC2 soap_hash(const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_endpoint(struct soap*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_flush_raw(struct soap*, const char*, size_t); +SOAP_FMAC1 int SOAP_FMAC2 soap_flush(struct soap*); +SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_get(struct soap*); +SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_getchar(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_tag_cmp(const char*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_fault(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_sender_fault(struct soap*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_sender_fault_subcode(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_receiver_fault(struct soap*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_receiver_fault_subcode(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_sender_error(struct soap*, const char*, const char*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_receiver_error(struct soap*, const char*, const char*, int); + +SOAP_FMAC1 int SOAP_FMAC2 soap_send_raw(struct soap*, const char*, size_t); +SOAP_FMAC1 int SOAP_FMAC2 soap_recv_raw(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_recv(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_send(struct soap*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_send2(struct soap*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_send3(struct soap*, const char*, const char*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_pututf8(struct soap*, unsigned long); +SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_getutf8(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_putbase64(struct soap*, const unsigned char*, int); +SOAP_FMAC1 unsigned char* SOAP_FMAC2 soap_getbase64(struct soap*, int*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_puthex(struct soap*, const unsigned char*, int); +SOAP_FMAC1 unsigned char* SOAP_FMAC2 soap_gethex(struct soap*, int*); + +#ifndef WITH_LEANER +SOAP_FMAC1 int SOAP_FMAC2 soap_xop_forward(struct soap*, unsigned char**, int*, char**, char**, char**); +SOAP_FMAC1 int SOAP_FMAC2 soap_dime_forward(struct soap*, unsigned char**, int*, char**, char**, char**); +#endif + +#ifndef WITH_NOIDREF +SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_lookup_id(struct soap*, void *p, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_lookup(struct soap*, const void *p, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_enter(struct soap*, const void *p, const struct soap_array *a, int n, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_array_pointer_lookup(struct soap*, const void *p, const struct soap_array *a, int n, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_embed(struct soap *soap, const void *p, const struct soap_array *a, int n, const char *tag, int type); +SOAP_FMAC1 struct soap_ilist* SOAP_FMAC2 soap_lookup(struct soap*, const char*); +SOAP_FMAC1 struct soap_ilist* SOAP_FMAC2 soap_enter(struct soap*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_resolve(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_embedded(struct soap*, const void *p, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_reference(struct soap*, const void *p, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_array_reference(struct soap*, const void *p, const struct soap_array *a, int n, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_embedded_id(struct soap*, int id, const void *p, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_is_embedded(struct soap*, struct soap_plist*); +SOAP_FMAC1 int SOAP_FMAC2 soap_is_single(struct soap*, struct soap_plist*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_embedded(struct soap*, struct soap_plist*); +#endif + +SOAP_FMAC1 int SOAP_FMAC2 soap_begin_count(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_end_count(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_begin_send(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_end_send(struct soap*); + +SOAP_FMAC1 const struct soap_code_map* SOAP_FMAC2 soap_code(const struct soap_code_map*, const char *str); +SOAP_FMAC1 long SOAP_FMAC2 soap_int_code(const struct soap_code_map*, const char *str, long other); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_str_code(const struct soap_code_map*, long code); + +SOAP_FMAC1 int SOAP_FMAC2 soap_getline(struct soap*, char*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_begin_recv(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_end_recv(struct soap*); + +SOAP_FMAC1 void* SOAP_FMAC2 soap_malloc(struct soap*, size_t); +SOAP_FMAC1 void SOAP_FMAC2 soap_dealloc(struct soap*, void*); +SOAP_FMAC1 struct soap_clist * SOAP_FMAC2 soap_link(struct soap*, void*, int, int, void (*fdelete)(struct soap_clist*)); +SOAP_FMAC1 void SOAP_FMAC2 soap_unlink(struct soap*, const void*); +SOAP_FMAC1 void SOAP_FMAC2 soap_free(struct soap*); + +SOAP_FMAC1 void* SOAP_FMAC2 soap_track_malloc(struct soap*, const char*, int, size_t); +SOAP_FMAC1 void SOAP_FMAC2 soap_track_free(struct soap*, const char*, int, void*); + +#ifndef WITH_NOIDREF +SOAP_FMAC1 int SOAP_FMAC2 soap_lookup_type(struct soap*, const char *id); +SOAP_FMAC1 void* SOAP_FMAC2 soap_id_lookup(struct soap*, const char *id, void **p, int t, size_t n, unsigned int k); +SOAP_FMAC1 void* SOAP_FMAC2 soap_id_forward(struct soap*, const char *id, void *p, int st, int tt, size_t n, unsigned int k, void(*fcopy)(struct soap*, int, int, void*, const void*, size_t)); +#endif +SOAP_FMAC1 void* SOAP_FMAC2 soap_id_enter(struct soap*, const char *id, void *p, int t, size_t n, unsigned int k, const char *type, const char *arrayType, void *(*finstantiate)(struct soap*, int, const char*, const char*, size_t*)); +SOAP_FMAC1 void SOAP_FMAC2 soap_fcopy(struct soap *soap, int st, int tt, void *p, const void *q, size_t n); + +SOAP_FMAC1 int SOAP_FMAC2 soap_size(const int *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_getoffsets(const char *, const int *, int *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_getsize(const char *, const char *, int *); +SOAP_FMAC1 int SOAP_FMAC2 soap_getsizes(const char *, int *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_getposition(const char *, int *); + +SOAP_FMAC1 char* SOAP_FMAC2 soap_putsize(struct soap*, const char *, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_putsizesoffsets(struct soap*, const char *, const int *, const int *, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_putsizes(struct soap*, const char *, const int *, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_putoffset(struct soap*, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_putoffsets(struct soap*, const int *, int); + +SOAP_FMAC1 int SOAP_FMAC2 soap_closesock(struct soap*); + +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_new(void); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_new1(soap_mode); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_new2(soap_mode, soap_mode); +SOAP_FMAC1 void SOAP_FMAC2 soap_del(struct soap*); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_copy(struct soap*); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_copy_context(struct soap*,struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_init(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_init1(struct soap*, soap_mode); +SOAP_FMAC1 void SOAP_FMAC2 soap_init2(struct soap*, soap_mode, soap_mode); +SOAP_FMAC1 void SOAP_FMAC2 soap_done(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_cleanup(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_begin(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_end(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_delete(struct soap*, void*); + +#ifdef SOAP_DEBUG +SOAP_FMAC1 void SOAP_FMAC2 soap_set_recv_logfile(struct soap*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_sent_logfile(struct soap*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_test_logfile(struct soap*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_close_logfiles(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_open_logfile(struct soap*, int); +#endif + +SOAP_FMAC1 const char* SOAP_FMAC2 soap_token(struct soap*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_value(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_match_tag(struct soap*, const char*, const char *); +SOAP_FMAC1 int SOAP_FMAC2 soap_match_array(struct soap*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_element(struct soap*, const char*, int, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_begin_out(struct soap*, const char *tag, int id, const char *type); +SOAP_FMAC1 int SOAP_FMAC2 soap_array_begin_out(struct soap*, const char *tag, int id, const char *type, const char *offset); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_ref(struct soap*, const char *tag, int id, int href); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_href(struct soap*, const char *tag, int id, const char *ref, const char *val); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_null(struct soap*, const char *tag, int id, const char *type); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_id(struct soap*, const char *tag, int id, const void *p, const struct soap_array *a, int d, const char *type, int n); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_result(struct soap*, const char *tag); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_end_out(struct soap*, const char *tag); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_start_end_out(struct soap*, const char *tag); + +SOAP_FMAC1 int SOAP_FMAC2 soap_attribute(struct soap*, const char*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_element_begin_in(struct soap*, const char *tag, int nillable); + +SOAP_FMAC1 int SOAP_FMAC2 soap_element_end_in(struct soap*, const char *tag); + +SOAP_FMAC1 int SOAP_FMAC2 soap_peek_element(struct soap*); + +SOAP_FMAC1 void SOAP_FMAC2 soap_retry(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_revert(struct soap*); + +SOAP_FMAC1 char* SOAP_FMAC2 soap_strdup(struct soap*, const char*); +SOAP_FMAC1 const char * SOAP_FMAC2 soap_strsearch(const char *big, const char *little); + +SOAP_FMAC1 int SOAP_FMAC2 soap_string_out(struct soap*, const char *s, int flag); +SOAP_FMAC1 char* SOAP_FMAC2 soap_string_in(struct soap*, int, long, long); + +#ifndef WITH_LEANER +SOAP_FMAC1 int SOAP_FMAC2 soap_wstring_out(struct soap*, const wchar_t *s, int flag); +SOAP_FMAC1 wchar_t* SOAP_FMAC2 soap_wstring_in(struct soap*, int, long, long); +#endif + +SOAP_FMAC1 int SOAP_FMAC2 soap_match_namespace(struct soap*, const char *, const char*, int n1, int n2); + +SOAP_FMAC1 int SOAP_FMAC2 soap_set_namespaces(struct soap*, struct Namespace*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_local_namespaces(struct soap*); + +SOAP_FMAC1 void SOAP_FMAC2 soap_pop_namespace(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_push_namespace(struct soap*, const char *,const char *); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_current_namespace(struct soap *soap, const char *tag); + +SOAP_FMAC1 int SOAP_FMAC2 soap_store_lab(struct soap*, const char*, size_t); +SOAP_FMAC1 int SOAP_FMAC2 soap_append_lab(struct soap*, const char*, size_t); + +SOAP_FMAC1 int SOAP_FMAC2 soap_new_block(struct soap*); +SOAP_FMAC1 void* SOAP_FMAC2 soap_push_block(struct soap*, size_t); +SOAP_FMAC1 void SOAP_FMAC2 soap_pop_block(struct soap*); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_size_block(struct soap*, size_t); +SOAP_FMAC1 char* SOAP_FMAC2 soap_first_block(struct soap*); +SOAP_FMAC1 char* SOAP_FMAC2 soap_next_block(struct soap*); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_block_size(struct soap*); +SOAP_FMAC1 char* SOAP_FMAC2 soap_save_block(struct soap*, char*, int); +SOAP_FMAC1 void SOAP_FMAC2 soap_end_block(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_begin_out(struct soap*); +SOAP_FMAC1 int soap_envelope_end_out(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_begin_in(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_end_in(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_body_begin_out(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_body_end_out(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_body_begin_in(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_body_end_in(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_recv_header(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_response(struct soap*, int); + +SOAP_FMAC1 int SOAP_FMAC2 soap_send_empty_response(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_recv_empty_response(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_send_fault(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_recv_fault(struct soap*); + +#ifndef WITH_NOSTDLIB +SOAP_FMAC1 void SOAP_FMAC2 soap_print_fault(struct soap*, FILE*); +SOAP_FMAC1 void SOAP_FMAC2 soap_print_fault_location(struct soap*, FILE*); +#endif + +SOAP_FMAC1 int SOAP_FMAC2 soap_s2byte(struct soap*, const char*, char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2short(struct soap*, const char*, short*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2int(struct soap*, const char*, int*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2long(struct soap*, const char*, long*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2LONG64(struct soap*, const char*, LONG64*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2float(struct soap*, const char*, float*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2double(struct soap*, const char*, double*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedByte(struct soap*, const char*, unsigned char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedShort(struct soap*, const char*, unsigned short*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedInt(struct soap*, const char*, unsigned int*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedLong(struct soap*, const char*, unsigned long*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2ULONG64(struct soap*, const char*, ULONG64*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2string(struct soap*, const char*, char**); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2QName(struct soap*, const char*, char**); + +#ifndef WITH_LEAN +SOAP_FMAC1 int SOAP_FMAC2 soap_s2wchar(struct soap*, const char*, wchar_t**); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2dateTime(struct soap*, const char*, time_t*); +SOAP_FMAC1 char* SOAP_FMAC2 soap_s2base64(struct soap*, const unsigned char*, char*, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_s2hex(struct soap*, const unsigned char*, char*, int); +#endif + +SOAP_FMAC1 const char* SOAP_FMAC2 soap_byte2s(struct soap*, char); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_short2s(struct soap*, short); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_int2s(struct soap*, int); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_long2s(struct soap*, long); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_LONG642s(struct soap*, LONG64); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_float2s(struct soap*, float); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_double2s(struct soap*, double); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedByte2s(struct soap*, unsigned char); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedShort2s(struct soap*, unsigned short); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedInt2s(struct soap*, unsigned int); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedLong2s(struct soap*, unsigned long); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_ULONG642s(struct soap*, ULONG64); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_QName2s(struct soap*, const char*); + +#ifndef WITH_LEAN +SOAP_FMAC1 const char* SOAP_FMAC2 soap_wchar2s(struct soap*, const wchar_t*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_dateTime2s(struct soap*, time_t); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_base642s(struct soap*, const char*, char*, size_t, int*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_hex2s(struct soap*, const char*, char*, size_t, int*); +#endif + + +SOAP_FMAC1 int* SOAP_FMAC2 soap_inint(struct soap*, const char *tag, int *p, const char *, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_inbyte(struct soap*, const char *tag, char *p, const char *, int); +SOAP_FMAC1 long* SOAP_FMAC2 soap_inlong(struct soap*, const char *tag, long *p, const char *, int); +SOAP_FMAC1 LONG64* SOAP_FMAC2 soap_inLONG64(struct soap*, const char *tag, LONG64 *p, const char *, int); +SOAP_FMAC1 short* SOAP_FMAC2 soap_inshort(struct soap*, const char *tag, short *p, const char *, int); +SOAP_FMAC1 float* SOAP_FMAC2 soap_infloat(struct soap*, const char *tag, float *p, const char *, int); +SOAP_FMAC1 double* SOAP_FMAC2 soap_indouble(struct soap*, const char *tag, double *p, const char *, int); +SOAP_FMAC1 unsigned char* SOAP_FMAC2 soap_inunsignedByte(struct soap*, const char *tag, unsigned char *p, const char *, int); +SOAP_FMAC1 unsigned short* SOAP_FMAC2 soap_inunsignedShort(struct soap*, const char *tag, unsigned short *p, const char *, int); +SOAP_FMAC1 unsigned int* SOAP_FMAC2 soap_inunsignedInt(struct soap*, const char *tag, unsigned int *p, const char *, int); +SOAP_FMAC1 unsigned long* SOAP_FMAC2 soap_inunsignedLong(struct soap*, const char *tag, unsigned long *p, const char *, int); +SOAP_FMAC1 ULONG64* SOAP_FMAC2 soap_inULONG64(struct soap*, const char *tag, ULONG64 *p, const char *, int); +SOAP_FMAC1 char** SOAP_FMAC2 soap_instring(struct soap*, const char *tag, char **p, const char *, int, int, long, long); +SOAP_FMAC1 char** SOAP_FMAC2 soap_inliteral(struct soap*, const char *tag, char **p); + +#ifndef WITH_LEAN +SOAP_FMAC1 time_t* SOAP_FMAC2 soap_indateTime(struct soap*, const char *tag, time_t *p, const char *, int); +#endif + +#ifndef WITH_LEANER +SOAP_FMAC1 wchar_t** SOAP_FMAC2 soap_inwstring(struct soap*, const char *tag, wchar_t **p, const char *, int, long, long); +SOAP_FMAC1 wchar_t** SOAP_FMAC2 soap_inwliteral(struct soap*, const char *tag, wchar_t **p); +#endif + +SOAP_FMAC1 int SOAP_FMAC2 soap_outbyte(struct soap*, const char *tag, int id, const char *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outshort(struct soap*, const char *tag, int id, const short *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outint(struct soap*, const char *tag, int id, const int *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outlong(struct soap*, const char *tag, int id, const long *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outLONG64(struct soap*, const char *tag, int id, const LONG64 *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outfloat(struct soap*, const char *tag, int id, const float *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outdouble(struct soap*, const char *tag, int id, const double *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedByte(struct soap*, const char *tag, int id, const unsigned char *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedShort(struct soap*, const char *tag, int id, const unsigned short *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedInt(struct soap*, const char *tag, int id, const unsigned int *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedLong(struct soap*, const char *tag, int id, const unsigned long *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outULONG64(struct soap*, const char *tag, int id, const ULONG64 *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outstring(struct soap*, const char *tag, int id, char *const*p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outliteral(struct soap*, const char *tag, char *const*p); + +#ifndef WITH_LEAN +SOAP_FMAC1 int SOAP_FMAC2 soap_outdateTime(struct soap*, const char *tag, int id, const time_t *p, const char *, int); +#endif + +#ifndef WITH_LEANER +SOAP_FMAC1 int SOAP_FMAC2 soap_outwstring(struct soap*, const char *tag, int id, wchar_t *const*p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outwliteral(struct soap*, const char *tag, wchar_t *const*p); +#endif + +#ifndef WITH_LEANER +SOAP_FMAC1 int SOAP_FMAC2 soap_attachment(struct soap *, const char*, int, const void*, const struct soap_array*, const char*, const char*, const char*, int, const char*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_move(struct soap*, long); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_tell(struct soap*); +SOAP_FMAC1 char* SOAP_FMAC2 soap_dime_option(struct soap*, unsigned short, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getdimehdr(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getdime(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putdimehdr(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putdime(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getmimehdr(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getmime(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putmimehdr(struct soap*, struct soap_multipart*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putmime(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_dime(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_mime(struct soap*, const char *boundary, const char *start); +SOAP_FMAC1 void SOAP_FMAC2 soap_clr_dime(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_clr_mime(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_dime_attachment(struct soap*, char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_mime_attachment(struct soap*, char *ptr, size_t size, enum soap_mime_encoding encoding, const char *type, const char *id, const char *location, const char *description); +SOAP_FMAC1 struct soap_multipart* SOAP_FMAC2 soap_next_multipart(struct soap_multipart*); +#endif + +SOAP_FMAC1 int SOAP_FMAC2 soap_register_plugin_arg(struct soap*, int (*fcreate)(struct soap*, struct soap_plugin*, void*), void*); +SOAP_FMAC1 void* SOAP_FMAC2 soap_lookup_plugin(struct soap*, const char*); + +SOAP_FMAC1 const char* SOAP_FMAC2 soap_attr_value(struct soap *soap, const char *name, int flag); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_attr(struct soap *soap, const char *name, const char *value); +SOAP_FMAC1 void SOAP_FMAC2 soap_clr_attr(struct soap *soap); + +#ifdef WITH_COOKIES +SOAP_FMAC1 size_t SOAP_FMAC2 soap_encode_cookie(const char*, char*, size_t); +SOAP_FMAC1 extern struct soap_cookie* SOAP_FMAC2 soap_set_cookie(struct soap*, const char*, const char*, const char*, const char*); +SOAP_FMAC1 extern struct soap_cookie* SOAP_FMAC2 soap_cookie(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern char* SOAP_FMAC2 soap_cookie_value(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern char* SOAP_FMAC2 soap_env_cookie_value(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern long SOAP_FMAC2 soap_cookie_expire(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern int SOAP_FMAC2 soap_set_cookie_expire(struct soap*, const char*, long, const char*, const char*); +SOAP_FMAC1 extern int SOAP_FMAC2 soap_set_cookie_session(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern int SOAP_FMAC2 soap_clr_cookie_session(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern void SOAP_FMAC2 soap_clr_cookie(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern int SOAP_FMAC2 soap_getenv_cookies(struct soap*); +SOAP_FMAC1 extern struct soap_cookie* SOAP_FMAC2 soap_copy_cookies(struct soap*); +SOAP_FMAC1 extern void SOAP_FMAC2 soap_free_cookies(struct soap*); +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif + diff --git a/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.9b.c b/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.9b.c new file mode 100644 index 0000000..959147e --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.9b.c @@ -0,0 +1,14172 @@ +/* + +stdsoap2.c[pp] 2.7.9b + +gSOAP runtime + +gSOAP XML Web services tools +Copyright (C) 2000-2007, Robert van Engelen, Genivia Inc., All Rights Reserved. +This part of the software is released under one of the following licenses: +GPL, the gSOAP public license, or Genivia's license for commercial use. +-------------------------------------------------------------------------------- +Contributors: + +Wind River Systems Inc., for the following additions under gSOAP public license: + - vxWorks compatible (#define VXWORKS) +-------------------------------------------------------------------------------- +gSOAP public license. + +The contents of this file are subject to the gSOAP Public License Version 1.3 +(the "License"); you may not use this file except in compliance with the +License. You may obtain a copy of the License at +http://www.cs.fsu.edu/~engelen/soaplicense.html +Software distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +for the specific language governing rights and limitations under the License. + +The Initial Developer of the Original Code is Robert A. van Engelen. +Copyright (C) 2000-2007, Robert van Engelen, Genivia Inc., All Rights Reserved. +-------------------------------------------------------------------------------- +GPL license. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA + +Author contact information: +engelen@genivia.com / engelen@acm.org +-------------------------------------------------------------------------------- +A commercial use license is available from Genivia, Inc., contact@genivia.com +-------------------------------------------------------------------------------- + +Installation note: + +Win32 build needs winsock.dll (Visual C++ "wsock32.lib") +To do this in Visual C++ 6.0, go to "Project", "settings", select the "Link" +tab (the project file needs to be selected in the file view) and add +"wsock32.lib" to the "Object/library modules" entry + +On Mac OS X with gcc (GCC) 3.1 20020420 (prerelease) you MUST compile with +-fstack_check when using -O2 because gcc 3.1 has a bug that smashes the stack +when locally allocated data exceeds 64K. + +*/ + +#ifdef AS400 +# pragma convert(819) /* EBCDIC to ASCII */ +#endif + +#include "stdsoap2.h" + +#ifdef WIN32 +# pragma comment(lib, "wsock32.lib") +#endif + +#ifdef __cplusplus +SOAP_SOURCE_STAMP("@(#) stdsoap2.cpp ver 2.7.9b 2007-01-01 12:00:00 GMT") +extern "C" { +#else +SOAP_SOURCE_STAMP("@(#) stdsoap2.c ver 2.7.9 2007-01-01 12:00:00 GMT") +#endif + +/* 8bit character representing unknown/nonrepresentable character data (e.g. not supported by current locale with multibyte support enabled) */ +#ifndef SOAP_UNKNOWN_CHAR +#define SOAP_UNKNOWN_CHAR (127) +#endif + +/* EOF=-1 */ +#define SOAP_LT (soap_wchar)(-2) /* XML character '<' */ +#define SOAP_TT (soap_wchar)(-3) /* XML character '' */ +#define SOAP_QT (soap_wchar)(-5) /* XML character '"' */ +#define SOAP_AP (soap_wchar)(-6) /* XML character ''' */ + +#define soap_blank(c) ((c) >= 0 && (c) <= 32) +#define soap_notblank(c) ((c) > 32) + +#define soap_hash_ptr(p) ((size_t)(((unsigned long)(p) >> 3) & (SOAP_PTRHASH-1))) + +#ifdef SOAP_DEBUG +static void soap_init_logs(struct soap*); +static void soap_close_logfile(struct soap*, int); +static void soap_set_logfile(struct soap*, int, const char*); +#endif + +#ifdef SOAP_MEM_DEBUG +static void soap_init_mht(struct soap*); +static void soap_free_mht(struct soap*); +static void soap_track_unlink(struct soap*, const void*); +#endif + +#ifndef PALM_2 +static int soap_set_error(struct soap*, const char*, const char*, const char*, const char*, int); +static int soap_copy_fault(struct soap*, const char*, const char*, const char*, const char*); +static int soap_getattrval(struct soap*, char*, size_t, soap_wchar); +#endif + +#ifndef PALM_1 +static soap_wchar soap_char(struct soap*); +static soap_wchar soap_get_pi(struct soap*); +static int soap_isxdigit(int); +static void *fplugin(struct soap*, const char*); +#ifndef WITH_NOIDREF +static void soap_update_ptrs(struct soap*, char*, char*, char*, char*); +static int soap_has_copies(struct soap*, const char*, const char*); +static void soap_init_iht(struct soap*); +static void soap_free_iht(struct soap*); +static void soap_init_pht(struct soap*); +static void soap_free_pht(struct soap*); +#endif +#endif + +#ifndef WITH_LEAN +static const char *soap_set_validation_fault(struct soap*, const char*, const char*); +static int soap_isnumeric(struct soap*, const char*); +static time_t soap_timegm(struct tm*); +static struct soap_nlist *soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized); +static void soap_pop_ns(struct soap *soap); +static void soap_utilize_ns(struct soap *soap, const char *tag, size_t n); +#endif + +#ifndef WITH_LEANER +#ifndef PALM_1 +static struct soap_multipart *soap_new_multipart(struct soap*, struct soap_multipart**, struct soap_multipart**, char*, size_t); +static int soap_putdimefield(struct soap*, const char*, size_t); +static char *soap_getdimefield(struct soap*, size_t); +static void soap_select_mime_boundary(struct soap*); +static int soap_valid_mime_boundary(struct soap*); +static void soap_resolve_attachment(struct soap*, struct soap_multipart*); +#endif +#endif + +#ifdef WITH_GZIP +static int soap_getgziphdr(struct soap*); +#endif + +#ifdef WITH_OPENSSL +static int ssl_init_done = 0; +static int ssl_auth_init(struct soap*); +static int ssl_verify_callback(int, X509_STORE_CTX*); +static int ssl_password(char*, int, int, void *); +/* This callback is included for future references. It should not be deleted +static DH *ssl_tmp_dh(SSL*, int, int); +*/ +#endif + +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +#ifndef PALM_1 +static const char *soap_decode(char*, size_t, const char*, const char*); +#endif +#endif + +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static soap_wchar soap_getchunkchar(struct soap*); +static const char *http_error(struct soap*, int); +static int http_post(struct soap*, const char*, const char*, int, const char*, const char*, size_t); +static int http_get(struct soap*); +static int http_send_header(struct soap*, const char*); +static int http_post_header(struct soap*, const char*, const char*); +static int http_response(struct soap*, int, size_t); +static int http_parse(struct soap*); +static int http_parse_header(struct soap*, const char*, const char*); +#endif +#endif + +#ifndef WITH_NOIO +#ifndef PALM_1 +static int fsend(struct soap*, const char*, size_t); +static size_t frecv(struct soap*, char*, size_t); +static int tcp_init(struct soap*); +static const char *tcp_error(struct soap*); +#ifndef WITH_LEAN +static size_t frecv_stop(struct soap*, char*, size_t); +#endif +#ifndef WITH_IPV6 +static int tcp_gethost(struct soap*, const char *addr, struct in_addr *inaddr); +#endif +static int tcp_connect(struct soap*, const char *endpoint, const char *host, int port); +static int tcp_accept(struct soap*, int, struct sockaddr*, int*); +static int tcp_disconnect(struct soap*); +static int tcp_closesocket(struct soap*, SOAP_SOCKET); +static int tcp_shutdownsocket(struct soap*, SOAP_SOCKET, int); +static const char *soap_strerror(struct soap*); +#endif +#endif + +#if defined(PALM) && !defined(PALM_2) +unsigned short errno; +#endif + +#ifndef PALM_1 +static const char soap_env1[42] = "http://schemas.xmlsoap.org/soap/envelope/"; +static const char soap_enc1[42] = "http://schemas.xmlsoap.org/soap/encoding/"; +static const char soap_env2[40] = "http://www.w3.org/2003/05/soap-envelope"; +static const char soap_enc2[40] = "http://www.w3.org/2003/05/soap-encoding"; +static const char soap_rpc[35] = "http://www.w3.org/2003/05/soap-rpc"; +#endif + +#ifndef PALM_1 +const struct soap_double_nan soap_double_nan = {0xFFFFFFFF, 0xFFFFFFFF}; +static const char soap_base64o[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char soap_base64i[81] = "\76XXX\77\64\65\66\67\70\71\72\73\74\75XXXXXXX\00\01\02\03\04\05\06\07\10\11\12\13\14\15\16\17\20\21\22\23\24\25\26\27\30\31XXXXXX\32\33\34\35\36\37\40\41\42\43\44\45\46\47\50\51\52\53\54\55\56\57\60\61\62\63"; +#endif + +#ifndef WITH_LEAN +static const char soap_indent[11] = "\n\t\t\t\t\t\t\t\t\t"; +/* Alternative indentation form for SOAP_XML_INDENT: +static const char soap_indent[21] = "\n "; +*/ +#endif + +#ifndef SOAP_CANARY +# define SOAP_CANARY (0xC0DE) +#endif + +static const char soap_padding[4] = "\0\0\0"; +#define SOAP_STR_PADDING (soap_padding) +#define SOAP_STR_EOS (soap_padding) +#define SOAP_NON_NULL (soap_padding) + +#ifndef WITH_LEAN +static const struct soap_code_map html_entity_codes[] = /* entities for XHTML parsing */ +{ { 160, "nbsp" }, + { 161, "iexcl" }, + { 162, "cent" }, + { 163, "pound" }, + { 164, "curren" }, + { 165, "yen" }, + { 166, "brvbar" }, + { 167, "sect" }, + { 168, "uml" }, + { 169, "copy" }, + { 170, "ordf" }, + { 171, "laquo" }, + { 172, "not" }, + { 173, "shy" }, + { 174, "reg" }, + { 175, "macr" }, + { 176, "deg" }, + { 177, "plusmn" }, + { 178, "sup2" }, + { 179, "sup3" }, + { 180, "acute" }, + { 181, "micro" }, + { 182, "para" }, + { 183, "middot" }, + { 184, "cedil" }, + { 185, "sup1" }, + { 186, "ordm" }, + { 187, "raquo" }, + { 188, "frac14" }, + { 189, "frac12" }, + { 190, "frac34" }, + { 191, "iquest" }, + { 192, "Agrave" }, + { 193, "Aacute" }, + { 194, "Acirc" }, + { 195, "Atilde" }, + { 196, "Auml" }, + { 197, "Aring" }, + { 198, "AElig" }, + { 199, "Ccedil" }, + { 200, "Egrave" }, + { 201, "Eacute" }, + { 202, "Ecirc" }, + { 203, "Euml" }, + { 204, "Igrave" }, + { 205, "Iacute" }, + { 206, "Icirc" }, + { 207, "Iuml" }, + { 208, "ETH" }, + { 209, "Ntilde" }, + { 210, "Ograve" }, + { 211, "Oacute" }, + { 212, "Ocirc" }, + { 213, "Otilde" }, + { 214, "Ouml" }, + { 215, "times" }, + { 216, "Oslash" }, + { 217, "Ugrave" }, + { 218, "Uacute" }, + { 219, "Ucirc" }, + { 220, "Uuml" }, + { 221, "Yacute" }, + { 222, "THORN" }, + { 223, "szlig" }, + { 224, "agrave" }, + { 225, "aacute" }, + { 226, "acirc" }, + { 227, "atilde" }, + { 228, "auml" }, + { 229, "aring" }, + { 230, "aelig" }, + { 231, "ccedil" }, + { 232, "egrave" }, + { 233, "eacute" }, + { 234, "ecirc" }, + { 235, "euml" }, + { 236, "igrave" }, + { 237, "iacute" }, + { 238, "icirc" }, + { 239, "iuml" }, + { 240, "eth" }, + { 241, "ntilde" }, + { 242, "ograve" }, + { 243, "oacute" }, + { 244, "ocirc" }, + { 245, "otilde" }, + { 246, "ouml" }, + { 247, "divide" }, + { 248, "oslash" }, + { 249, "ugrave" }, + { 250, "uacute" }, + { 251, "ucirc" }, + { 252, "uuml" }, + { 253, "yacute" }, + { 254, "thorn" }, + { 255, "yuml" }, + { 0, NULL } +}; +#endif + +#ifndef WITH_NOIO +#ifndef WITH_LEAN +static const struct soap_code_map h_error_codes[] = +{ +#ifdef HOST_NOT_FOUND + { HOST_NOT_FOUND, "Host not found" }, +#endif +#ifdef TRY_AGAIN + { TRY_AGAIN, "Try Again" }, +#endif +#ifdef NO_RECOVERY + { NO_RECOVERY, "No Recovery" }, +#endif +#ifdef NO_DATA + { NO_DATA, "No Data" }, +#endif +#ifdef NO_ADDRESS + { NO_ADDRESS, "No Address" }, +#endif + { 0, NULL } +}; +#endif +#endif + +#ifndef WITH_NOHTTP +#ifndef WITH_LEAN +static const struct soap_code_map h_http_error_codes[] = +{ { 200, "OK" }, + { 201, "Created" }, + { 202, "Accepted" }, + { 203, "Non-Authoritative Information" }, + { 204, "No Content" }, + { 205, "Reset Content" }, + { 206, "Partial Content" }, + { 300, "Multiple Choices" }, + { 301, "Moved Permanently" }, + { 302, "Found" }, + { 303, "See Other" }, + { 304, "Not Modified" }, + { 305, "Use Proxy" }, + { 307, "Temporary Redirect" }, + { 400, "Bad Request" }, + { 401, "Unauthorized" }, + { 402, "Payment Required" }, + { 403, "Forbidden" }, + { 404, "Not Found" }, + { 405, "Method Not Allowed" }, + { 406, "Not Acceptable" }, + { 407, "Proxy Authentication Required" }, + { 408, "Request Time-out" }, + { 409, "Conflict" }, + { 410, "Gone" }, + { 411, "Length Required" }, + { 412, "Precondition Failed" }, + { 413, "Request Entity Too Large" }, + { 414, "Request-URI Too Large" }, + { 415, "Unsupported Media Type" }, + { 416, "Requested range not satisfiable" }, + { 417, "Expectation Failed" }, + { 500, "Internal Server Error" }, + { 501, "Not Implemented" }, + { 502, "Bad Gateway" }, + { 503, "Service Unavailable" }, + { 504, "Gateway Time-out" }, + { 505, "HTTP Version not supported" }, + { 0, NULL } +}; +#endif +#endif + +#ifdef WITH_OPENSSL +static const struct soap_code_map h_ssl_error_codes[] = +{ +#define _SSL_ERROR(e) { e, #e } + _SSL_ERROR(SSL_ERROR_SSL), + _SSL_ERROR(SSL_ERROR_ZERO_RETURN), + _SSL_ERROR(SSL_ERROR_WANT_READ), + _SSL_ERROR(SSL_ERROR_WANT_WRITE), + _SSL_ERROR(SSL_ERROR_WANT_CONNECT), + _SSL_ERROR(SSL_ERROR_WANT_X509_LOOKUP), + _SSL_ERROR(SSL_ERROR_SYSCALL), + { 0, NULL } +}; +#endif + +#ifndef WITH_LEANER +static const struct soap_code_map mime_codes[] = +{ { SOAP_MIME_7BIT, "7bit" }, + { SOAP_MIME_8BIT, "8bit" }, + { SOAP_MIME_BINARY, "binary" }, + { SOAP_MIME_QUOTED_PRINTABLE, "quoted-printable" }, + { SOAP_MIME_BASE64, "base64" }, + { SOAP_MIME_IETF_TOKEN, "ietf-token" }, + { SOAP_MIME_X_TOKEN, "x-token" }, + { 0, NULL } +}; +#endif + +#ifdef WIN32 +static int tcp_done = 0; +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +fsend(struct soap *soap, const char *s, size_t n) +{ register int nwritten, err; +#if defined(__cplusplus) && !defined(WITH_LEAN) + if (soap->os) + { soap->os->write(s, n); + if (soap->os->good()) + return SOAP_OK; + return SOAP_EOF; + } +#endif + while (n) + { if (soap_valid_socket(soap->socket)) + { +#ifndef WITH_LEAN + if (soap->send_timeout) + { struct timeval timeout; + fd_set fd; + if (soap->send_timeout > 0) + { timeout.tv_sec = soap->send_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->send_timeout/1000000; + timeout.tv_usec = -soap->send_timeout%1000000; + } +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + return SOAP_FD_EXCEEDED; /* Hint: MUST increase FD_SETSIZE */ +#endif + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->socket, &fd); + for (;;) + { register int r = select((SOAP_SOCKET)(soap->socket + 1), NULL, &fd, &fd, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + return SOAP_EOF; + } + err = soap_socket_errno(soap->socket); + if (err != SOAP_EINTR && err != SOAP_EAGAIN) + { soap->errnum = err; + return SOAP_EOF; + } + } + } +#endif +#ifdef WITH_OPENSSL + if (soap->ssl) + nwritten = SSL_write(soap->ssl, s, n); + else if (soap->bio) + nwritten = BIO_write(soap->bio, s, n); + else +#endif +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + { if (soap->peerlen) + nwritten = sendto((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags, (struct sockaddr*)&soap->peer, soap->peerlen); + else + nwritten = send((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags); + /* retry and back-off algorithm */ + /* TODO: this is not very clear from specs so verify and limit conditions under which we should loop (e.g. ENOBUFS) */ + if (nwritten < 0) + { struct timeval timeout; + fd_set fd; + int udp_repeat; + int udp_delay; +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + return SOAP_FD_EXCEEDED; /* Hint: MUST increase FD_SETSIZE */ +#endif + if ((soap->connect_flags & SO_BROADCAST)) + udp_repeat = 3; /* SOAP-over-UDP MULTICAST_UDP_REPEAT - 1 */ + else + udp_repeat = 1; /* SOAP-over-UDP UNICAST_UDP_REPEAT - 1 */ + udp_delay = (soap_random % 201) + 50; /* UDP_MIN_DELAY .. UDP_MAX_DELAY */ + do + { timeout.tv_sec = 0; + timeout.tv_usec = 1000 * udp_delay; /* ms */ + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->socket, &fd); + select((SOAP_SOCKET)(soap->socket + 1), NULL, NULL, &fd, &timeout); + if (soap->peerlen) + nwritten = sendto((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags, (struct sockaddr*)&soap->peer, soap->peerlen); + else + nwritten = send((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags); + udp_delay <<= 1; + if (udp_delay > 500) /* UDP_UPPER_DELAY */ + udp_delay = 500; + } + while (nwritten < 0 && --udp_repeat > 0); + } + } + else +#endif +#if !defined(PALM) && !defined(AS400) + nwritten = send((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags); +#else + nwritten = send((SOAP_SOCKET)soap->socket, (void*)s, n, soap->socket_flags); +#endif + if (nwritten <= 0) + { +#ifdef WITH_OPENSSL + int err; + if (soap->ssl && (err = SSL_get_error(soap->ssl, nwritten)) != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) + return SOAP_EOF; +#endif + err = soap_socket_errno(soap->socket); + if (err && err != SOAP_EINTR && err != SOAP_EWOULDBLOCK && err != SOAP_EAGAIN) + { soap->errnum = err; + return SOAP_EOF; + } + nwritten = 0; /* and call write() again */ + } + } + else + { +#ifdef WITH_FASTCGI + nwritten = fwrite((void*)s, 1, n, stdout); + fflush(stdout); +#else +#ifdef UNDER_CE + nwritten = fwrite(s, 1, n, soap->sendfd); +#else +#ifdef VXWORKS +#ifdef WMW_RPM_IO + if (soap->rpmreqid) + nwritten = (httpBlockPut(soap->rpmreqid, s, n) == 0) ? n : -1; + else +#endif + nwritten = fwrite(s, sizeof(char), n, fdopen(soap->sendfd, "w")); +#else + nwritten = write((SOAP_SOCKET)soap->sendfd, s, n); +#endif +#endif +#endif + if (nwritten <= 0) + { err = soap_errno; + if (err && err != SOAP_EINTR && err != SOAP_EWOULDBLOCK && err != SOAP_EAGAIN) + { soap->errnum = err; + return SOAP_EOF; + } + nwritten = 0; /* and call write() again */ + } + } + n -= nwritten; + s += nwritten; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send_raw(struct soap *soap, const char *s, size_t n) +{ if (!n) + return SOAP_OK; + if (soap->mode & SOAP_IO_LENGTH) + { soap->count += n; +#ifndef WITH_LEANER + if (soap->fpreparesend && (soap->mode & SOAP_IO) != SOAP_IO_STORE) + return soap->error = soap->fpreparesend(soap, s, n); +#endif + return SOAP_OK; + } + if (soap->mode & SOAP_IO) + { register size_t i = SOAP_BUFLEN - soap->bufidx; + while (n >= i) + { memcpy(soap->buf + soap->bufidx, s, i); + soap->bufidx = SOAP_BUFLEN; + if (soap_flush(soap)) + return soap->error; + s += i; + n -= i; + i = SOAP_BUFLEN; + } + memcpy(soap->buf + soap->bufidx, s, n); + soap->bufidx += n; + return SOAP_OK; + } + return soap_flush_raw(soap, s, n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_flush(struct soap *soap) +{ register int n = soap->bufidx; + if (n) + { soap->bufidx = 0; +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { soap->d_stream.next_in = (Byte*)soap->buf; + soap->d_stream.avail_in = (unsigned int)n; +#ifdef WITH_GZIP + soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)n); +#endif + do + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating %u bytes\n", soap->d_stream.avail_in)); + if (deflate(&soap->d_stream, Z_NO_FLUSH) != Z_OK) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to deflate: %s\n", soap->d_stream.msg?soap->d_stream.msg:"")); + return soap->error = SOAP_ZLIB_ERROR; + } + if (!soap->d_stream.avail_out) + { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN)) + return soap->error; + soap->d_stream.next_out = (Byte*)soap->z_buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + } + } while (soap->d_stream.avail_in); + } + else +#endif + return soap_flush_raw(soap, soap->buf, n); + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_flush_raw(struct soap *soap, const char *s, size_t n) +{ if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) + { register char *t; + if (!(t = (char*)soap_push_block(soap, n))) + return soap->error = SOAP_EOM; + memcpy(t, s, n); +#ifndef WITH_LEANER + if (soap->fpreparesend) + return soap->error = soap->fpreparesend(soap, s, n); +#endif + return SOAP_OK; + } +#ifndef WITH_LEANER + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) + { char t[16]; + sprintf(t, "\r\n%lX\r\n" + (soap->chunksize ? 0 : 2), (unsigned long)n); + DBGMSG(SENT, t, strlen(t)); + if ((soap->error = soap->fsend(soap, t, strlen(t)))) + return soap->error; + soap->chunksize += n; + } + DBGMSG(SENT, s, n); +#endif + return soap->error = soap->fsend(soap, s, n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send(struct soap *soap, const char *s) +{ if (s) + return soap_send_raw(soap, s, strlen(s)); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send2(struct soap *soap, const char *s1, const char *s2) +{ if (soap_send(soap, s1)) + return soap->error; + return soap_send(soap, s2); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send3(struct soap *soap, const char *s1, const char *s2, const char *s3) +{ if (soap_send(soap, s1) + || soap_send(soap, s2)) + return soap->error; + return soap_send(soap, s3); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static size_t +frecv(struct soap *soap, char *s, size_t n) +{ register int r; +#ifdef PALM + register int timeouts = 0; +#endif + soap->errnum = 0; +#if defined(__cplusplus) && !defined(WITH_LEAN) + if (soap->is) + { if (soap->is->good()) + return soap->is->read(s, n).gcount(); + return 0; + } +#endif + if (soap_valid_socket(soap->socket)) + { for (;;) + { +#ifndef WITH_LEAN + if (soap->recv_timeout) + { struct timeval timeout; + fd_set fd; + if (soap->recv_timeout > 0) + { timeout.tv_sec = soap->recv_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->recv_timeout/1000000; + timeout.tv_usec = -soap->recv_timeout%1000000; + } +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + { soap->error = SOAP_FD_EXCEEDED; + return 0; /* Hint: MUST increase FD_SETSIZE */ + } +#endif + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->socket, &fd); + for (;;) + { r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + return 0; + } + r = soap_socket_errno(soap->socket); + if (r != SOAP_EINTR && r != SOAP_EAGAIN) + { soap->errnum = r; + return 0; + } + } + } +#endif +#ifdef WITH_OPENSSL + if (soap->ssl) + { int err; + r = SSL_read(soap->ssl, s, n); + if (r > 0) + return (size_t)r; + err = SSL_get_error(soap->ssl, r); + if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) + return 0; + } + else if (soap->bio) + { r = BIO_read(soap->bio, s, n); + if (r > 0) + return (size_t)r; + return 0; + } + else +#endif + { +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + { SOAP_SOCKLEN_T k = (SOAP_SOCKLEN_T)sizeof(soap->peer); + memset((void*)&soap->peer, 0, sizeof(soap->peer)); + r = recvfrom((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags, (struct sockaddr*)&soap->peer, &k); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */ + soap->peerlen = (size_t)k; +#ifndef WITH_IPV6 + soap->ip = ntohl(soap->peer.sin_addr.s_addr); +#endif + } + else +#endif + r = recv((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags); +#ifdef PALM + /* CycleSyncDisplay(curStatusMsg); */ +#endif + if (r >= 0) + return (size_t)r; + r = soap_socket_errno(soap->socket); + if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK) + { soap->errnum = r; + return 0; + } + } +#ifndef WITH_LEAN + { struct timeval timeout; + fd_set fd; + timeout.tv_sec = 0; + timeout.tv_usec = 10000; +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + { soap->error = SOAP_FD_EXCEEDED; + return 0; /* Hint: MUST increase FD_SETSIZE */ + } +#endif + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->socket, &fd); +#ifdef WITH_OPENSSL + if (soap->ssl && SSL_get_error(soap->ssl, r) == SSL_ERROR_WANT_WRITE) + r = select((SOAP_SOCKET)(soap->socket + 1), NULL, &fd, &fd, &timeout); + else + r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout); +#else + r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout); +#endif + if (r < 0 && (r = soap_socket_errno(soap->socket)) != SOAP_EINTR) + { soap->errnum = r; + return 0; + } + } +#endif +#ifdef PALM + if (r < 0 && (r = soap_socket_errno(soap->socket)) == SOAP_EINTR) + { timeouts++; + if (timeouts > 10) + { soap->errnum = r; + return 0; + } + } +#endif + } + } +#ifdef WITH_FASTCGI + return fread(s, 1, n, stdin); +#else +#ifdef UNDER_CE + return fread(s, 1, n, soap->recvfd); +#else +#ifdef WMW_RPM_IO + if (soap->rpmreqid) + r = httpBlockRead(soap->rpmreqid, s, n); + else +#endif + r = read((SOAP_SOCKET)soap->recvfd, s, n); + if (r >= 0) + return (size_t)r; + soap->errnum = soap_errno; + return 0; +#endif +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +#ifndef WITH_NOIO +#ifndef PALM_1 +static size_t +frecv_stop(struct soap *soap, char *s, size_t n) +{ return 0; +} +#endif +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static soap_wchar +soap_getchunkchar(struct soap *soap) +{ if (soap->bufidx < soap->buflen) + return soap->buf[soap->bufidx++]; + soap->bufidx = 0; + soap->buflen = soap->chunkbuflen = soap->frecv(soap, soap->buf, SOAP_BUFLEN); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket %d\n", (unsigned int)soap->buflen, soap->socket)); + DBGMSG(RECV, soap->buf, soap->buflen); + if (soap->buflen) + return soap->buf[soap->bufidx++]; + return EOF; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +soap_isxdigit(int c) +{ return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv_raw(struct soap *soap) +{ register size_t ret; +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { if (soap->d_stream.next_out == Z_NULL) + return EOF; + if (soap->d_stream.avail_in || !soap->d_stream.avail_out) + { register int r; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflating\n")); + soap->d_stream.next_out = (Byte*)soap->buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + r = inflate(&soap->d_stream, Z_NO_FLUSH); + if (r == Z_OK || r == Z_STREAM_END) + { soap->bufidx = 0; + ret = soap->buflen = SOAP_BUFLEN - soap->d_stream.avail_out; + if (soap->zlib_in == SOAP_ZLIB_GZIP) + soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)ret); + if (r == Z_STREAM_END) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out)); + soap->z_ratio_in = (float)soap->d_stream.total_in / (float)soap->d_stream.total_out; + soap->d_stream.next_out = Z_NULL; + } + if (ret) + { soap->count += ret; + DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- decompressed ----\n")); + DBGMSG(RECV, soap->buf, ret); + return SOAP_OK; + } + } + else if (r != Z_BUF_ERROR) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate error: %s\n", soap->d_stream.msg?soap->d_stream.msg:"")); + soap->d_stream.next_out = Z_NULL; + soap->error = SOAP_ZLIB_ERROR; + return EOF; + } + } +zlib_again: + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK && !soap->chunksize) + { memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN); + soap->buflen = soap->z_buflen; + } + DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- compressed ----\n")); + } +#endif +#ifndef WITH_NOHTTP + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) /* read HTTP chunked transfer */ + { +chunk_again: + if (soap->chunksize) + { soap->buflen = ret = soap->frecv(soap, soap->buf, soap->chunksize > SOAP_BUFLEN ? SOAP_BUFLEN : soap->chunksize); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk: read %u bytes\n", (unsigned int)ret)); + DBGMSG(RECV, soap->buf, ret); + soap->bufidx = 0; + soap->chunksize -= ret; + } + else + { register soap_wchar c; + char *t, tmp[8]; + t = tmp; + if (!soap->chunkbuflen) + { soap->chunkbuflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes (chunked) from socket %d\n", (unsigned int)ret, soap->socket)); + DBGMSG(RECV, soap->buf, ret); + soap->bufidx = 0; + if (!ret) + return soap->ahead = EOF; + } + else + soap->bufidx = soap->buflen; + soap->buflen = soap->chunkbuflen; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk size (idx=%u len=%u)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen)); + while (!soap_isxdigit((int)(c = soap_getchunkchar(soap)))) + { if ((int)c == EOF) + return soap->ahead = EOF; + } + do + *t++ = (char)c; + while (soap_isxdigit((int)(c = soap_getchunkchar(soap))) && t - tmp < 7); + while ((int)c != EOF && c != '\n') + c = soap_getchunkchar(soap); + if ((int)c == EOF) + return soap->ahead = EOF; + *t = '\0'; + soap->chunksize = soap_strtoul(tmp, &t, 16); + if (!soap->chunksize) + { soap->chunkbuflen = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of chunked message\n")); + while ((int)c != EOF && c != '\n') + c = soap_getchunkchar(soap); + return soap->ahead = EOF; + } + soap->buflen = soap->bufidx + soap->chunksize; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving buf len to idx=%u len=%u (%s)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen, tmp)); + if (soap->buflen > soap->chunkbuflen) + { soap->buflen = soap->chunkbuflen; + soap->chunksize -= soap->buflen - soap->bufidx; + soap->chunkbuflen = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Passed end of buffer for chunked HTTP (%u bytes left)\n", (unsigned int)(soap->buflen - soap->bufidx))); + } + else if (soap->chunkbuflen) + soap->chunksize = 0; + ret = soap->buflen - soap->bufidx; + if (!ret) + goto chunk_again; + } + } + else +#endif + { soap->bufidx = 0; + soap->buflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket %d\n", (unsigned int)ret, soap->socket)); + DBGMSG(RECV, soap->buf, ret); + } +#ifndef WITH_LEANER + if (soap->fpreparerecv && (soap->error = soap->fpreparerecv(soap, soap->buf, ret))) + return soap->error; +#endif +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { register int r; + memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); + soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx); + soap->d_stream.avail_in = (unsigned int)ret; + soap->d_stream.next_out = (Byte*)soap->buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + r = inflate(&soap->d_stream, Z_NO_FLUSH); + if (r == Z_OK || r == Z_STREAM_END) + { soap->bufidx = 0; + soap->z_buflen = soap->buflen; + soap->buflen = ret = SOAP_BUFLEN - soap->d_stream.avail_out; + if (soap->zlib_in == SOAP_ZLIB_GZIP) + soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %u bytes\n", (unsigned int)ret)); + if (!ret) + goto zlib_again; + if (r == Z_STREAM_END) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out)); + soap->z_ratio_in = (float)soap->d_stream.total_in / (float)soap->d_stream.total_out; + soap->d_stream.next_out = Z_NULL; + } + DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- decompressed ----\n")); + DBGMSG(RECV, soap->buf, ret); + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to inflate: (%d) %s\n", r, soap->d_stream.msg?soap->d_stream.msg:"")); + soap->d_stream.next_out = Z_NULL; + soap->error = SOAP_ZLIB_ERROR; + return EOF; + } + } +#endif + soap->count += ret; + return !ret; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv(struct soap *soap) +{ +#ifndef WITH_LEANER + if (soap->mode & SOAP_ENC_DIME) + { if (soap->dime.buflen) + { char *s; + int i; + unsigned char tmp[12]; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME hdr for chunked DIME is in buffer\n")); + soap->count += soap->dime.buflen - soap->buflen; + soap->buflen = soap->dime.buflen; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Skip padding (%ld bytes)\n", -(long)soap->dime.size&3)); + for (i = -(long)soap->dime.size&3; i > 0; i--) + { soap->bufidx++; + if (soap->bufidx >= soap->buflen) + if (soap_recv_raw(soap)) + return EOF; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME hdr for next chunk\n")); + s = (char*)tmp; + for (i = 12; i > 0; i--) + { *s++ = soap->buf[soap->bufidx++]; + if (soap->bufidx >= soap->buflen) + if (soap_recv_raw(soap)) + return EOF; + } + soap->dime.flags = tmp[0] & 0x7; + soap->dime.size = ((size_t)tmp[8] << 24) | ((size_t)tmp[9] << 16) | ((size_t)tmp[10] << 8) | ((size_t)tmp[11]); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME chunk (%u bytes)\n", (unsigned int)soap->dime.size)); + if (soap->dime.flags & SOAP_DIME_CF) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "More chunking\n")); + soap->dime.chunksize = soap->dime.size; + if (soap->buflen - soap->bufidx >= soap->dime.size) + { soap->dime.buflen = soap->buflen; + soap->buflen = soap->bufidx + soap->dime.chunksize; + } + else + soap->dime.chunksize -= soap->buflen - soap->bufidx; + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Last chunk\n")); + soap->dime.buflen = 0; + soap->dime.chunksize = 0; + } + soap->count = soap->buflen - soap->bufidx; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%u bytes remaining\n", (unsigned int)soap->count)); + return SOAP_OK; + } + if (soap->dime.chunksize) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get next DIME hdr for chunked DIME (%u bytes chunk)\n", (unsigned int)soap->dime.chunksize)); + if (soap_recv_raw(soap)) + return EOF; + if (soap->buflen - soap->bufidx >= soap->dime.chunksize) + { soap->dime.buflen = soap->buflen; + soap->count -= soap->buflen - soap->bufidx - soap->dime.chunksize; + soap->buflen = soap->bufidx + soap->dime.chunksize; + } + else + soap->dime.chunksize -= soap->buflen - soap->bufidx; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%lu bytes remaining, count=%u\n", (unsigned long)(soap->buflen-soap->bufidx), (unsigned int)soap->count)); + return SOAP_OK; + } + } +#endif + return soap_recv_raw(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +soap_wchar +SOAP_FMAC2 +soap_getchar(struct soap *soap) +{ register soap_wchar c; + c = soap->ahead; + if (c) + { if (c != EOF) + soap->ahead = 0; + return c; + } + return soap_get1(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +const struct soap_code_map* +SOAP_FMAC2 +soap_code(const struct soap_code_map *code_map, const char *str) +{ if (code_map && str) + { while (code_map->string) + { if (!strcmp(str, code_map->string)) /* case sensitive */ + return code_map; + code_map++; + } + } + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +long +SOAP_FMAC2 +soap_code_int(const struct soap_code_map *code_map, const char *str, long other) +{ if (code_map) + { while (code_map->string) + { if (!soap_tag_cmp(str, code_map->string)) /* case insensitive */ + return code_map->code; + code_map++; + } + } + return other; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_code_str(const struct soap_code_map *code_map, long code) +{ if (!code_map) + return NULL; + while (code_map->code != code && code_map->string) + code_map++; + return code_map->string; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +long +SOAP_FMAC2 +soap_code_bits(const struct soap_code_map *code_map, const char *str) +{ register long bits = 0; + if (code_map) + { while (str && *str) + { const struct soap_code_map *p; + for (p = code_map; p->string; p++) + { register size_t n = strlen(p->string); + if (!strncmp(p->string, str, n) && soap_blank(str[n])) + { bits |= p->code; + str += n; + while (*str > 0 && *str <= 32) + str++; + break; + } + } + if (!p->string) + return 0; + } + } + return bits; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_code_list(struct soap *soap, const struct soap_code_map *code_map, long code) +{ register char *t = soap->tmpbuf; + if (code_map) + { while (code_map->string) + { if (code_map->code & code) + { register const char *s = code_map->string; + if (t != soap->tmpbuf) + *t++ = ' '; + while (*s && t < soap->tmpbuf + sizeof(soap->tmpbuf) - 1) + *t++ = *s++; + if (t == soap->tmpbuf + sizeof(soap->tmpbuf) - 1) + break; + } + code_map++; + } + } + *t = '\0'; + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static soap_wchar +soap_char(struct soap *soap) +{ char tmp[8]; + register int i; + register soap_wchar c; + register char *s = tmp; + for (i = 0; i < 7; i++) + { c = soap_get1(soap); + if (c == ';' || (int)c == EOF) + break; + *s++ = (char)c; + } + *s = '\0'; + if (*tmp == '#') + { if (tmp[1] == 'x' || tmp[1] == 'X') + return soap_strtol(tmp + 2, NULL, 16); + return atol(tmp + 1); + } + if (!strcmp(tmp, "lt")) + return '<'; + if (!strcmp(tmp, "gt")) + return '>'; + if (!strcmp(tmp, "amp")) + return '&'; + if (!strcmp(tmp, "quot")) + return '"'; + if (!strcmp(tmp, "apos")) + return '\''; +#ifndef WITH_LEAN + return (soap_wchar)soap_code_int(html_entity_codes, tmp, SOAP_UNKNOWN_CHAR); +#else + return SOAP_UNKNOWN_CHAR; /* use this to represent unknown code */ +#endif +} +#endif + +/******************************************************************************/ +#ifdef WITH_LEAN +#ifndef PALM_1 +soap_wchar +soap_get0(struct soap *soap) +{ if (soap->bufidx >= soap->buflen && soap_recv(soap)) + return EOF; + return (unsigned char)soap->buf[soap->bufidx]; +} +#endif +#endif + +/******************************************************************************/ +#ifdef WITH_LEAN +#ifndef PALM_1 +soap_wchar +soap_get1(struct soap *soap) +{ if (soap->bufidx >= soap->buflen && soap_recv(soap)) + return EOF; + return (unsigned char)soap->buf[soap->bufidx++]; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +soap_wchar +SOAP_FMAC2 +soap_get(struct soap *soap) +{ register soap_wchar c; + c = soap->ahead; + if (c) + { if ((int)c != EOF) + soap->ahead = 0; + } + else + c = soap_get1(soap); + while ((int)c != EOF) + { if (soap->cdata) + { if (c == ']') + { c = soap_get1(soap); + if (c == ']') + { c = soap_get0(soap); + if (c == '>') + { soap->cdata = 0; + soap_get1(soap); + c = soap_get1(soap); + } + else + { soap_unget(soap, ']'); + return ']'; + } + } + else + { soap_revget1(soap); + return ']'; + } + } + else + return c; + } + switch (c) + { case '<': + do c = soap_get1(soap); + while (soap_blank(c)); + if (c == '!' || c == '?' || c == '%') + { register int k = 1; + if (c == '!') + { c = soap_get1(soap); + if (c == '[') + { do c = soap_get1(soap); + while ((int)c != EOF && c != '['); + if ((int)c == EOF) + break; + soap->cdata = 1; + c = soap_get1(soap); + continue; + } + if (c == '-' && (c = soap_get1(soap)) == '-') + { do + { c = soap_get1(soap); + if (c == '-' && (c = soap_get1(soap)) == '-') + break; + } while ((int)c != EOF); + } + } + else if (c == '?') + c = soap_get_pi(soap); + while ((int)c != EOF) + { if (c == '<') + k++; + else if (c == '>') + { if (--k <= 0) + break; + } + c = soap_get1(soap); + } + if ((int)c == EOF) + break; + c = soap_get1(soap); + continue; + } + if (c == '/') + return SOAP_TT; + soap_revget1(soap); + return SOAP_LT; + case '>': + return SOAP_GT; + case '"': + return SOAP_QT; + case '\'': + return SOAP_AP; + case '&': + return soap_char(soap) | 0x80000000; + } + break; + } + return c; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static soap_wchar +soap_get_pi(struct soap *soap) +{ char buf[64]; + register char *s = buf; + register int i = sizeof(buf); + register soap_wchar c = soap_getchar(soap); + /* This is a quick way to parse XML PI and we could use a callback instead to + * enable applications to intercept processing instructions */ + while ((int)c != EOF && c != '?') + { if (--i > 0) + { if (soap_blank(c)) + c = ' '; + *s++ = (char)c; + } + c = soap_getchar(soap); + } + *s = '\0'; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "XML PI \n", buf)); + if (!strncmp(buf, "xml ", 4)) + { s = strstr(buf, " encoding="); + if (s && s[10]) + { if (!soap_tag_cmp(s + 11, "iso-8859-1*") + || !soap_tag_cmp(s + 11, "latin1*")) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to latin1 encoding\n")); + soap->mode |= SOAP_ENC_LATIN; + } + else if (!soap_tag_cmp(s + 11, "utf-8*")) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to utf-8 encoding\n")); + soap->mode &= ~SOAP_ENC_LATIN; + } + } + } + if ((int)c != EOF) + c = soap_getchar(soap); + return c; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_move(struct soap *soap, long n) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving %ld bytes forward\n", (long)n)); + for (; n > 0; n--) + if ((int)soap_getchar(soap) == EOF) + return SOAP_EOF; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_tell(struct soap *soap) +{ return soap->count - soap->buflen + soap->bufidx - (soap->ahead != 0); +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_pututf8(struct soap *soap, register unsigned long c) +{ char tmp[16]; + if (c < 0x80 && c >= 0x20) + { *tmp = (char)c; + return soap_send_raw(soap, tmp, 1); + } +#ifndef WITH_LEAN + if (c >= 0x80 && (soap->mode & SOAP_XML_CANONICAL)) + { register char *t = tmp; + if (c < 0x0800) + *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); + else + { if (c < 0x010000) + *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + else + { if (c < 0x200000) + *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + else + { if (c < 0x04000000) + *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + else + { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + } + *t++ = (char)(0x80 | (c & 0x3F)); + *t = '\0'; + } + else +#endif + sprintf(tmp, "&#%lu;", c); + return soap_send(soap, tmp); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +soap_wchar +SOAP_FMAC2 +soap_getutf8(struct soap *soap) +{ register soap_wchar c, c1, c2, c3, c4; + c = soap->ahead; + if (c > 0xFF) + { soap->ahead = 0; + return c; + } +again: + c = soap_get(soap); + if (c < 0x80 || (soap->mode & SOAP_ENC_LATIN)) + return c; + c1 = soap_get1(soap); + if (c1 < 0x80) + { soap_revget1(soap); /* doesn't look like this is UTF8 */ + return c; + } + c1 &= 0x3F; + if (c < 0xE0) + return ((soap_wchar)(c & 0x1F) << 6) | c1; + c2 = (soap_wchar)soap_get1(soap) & 0x3F; + if (c == 0xEF && c1 == 0x3B && c2 == 0x3F) /* ignore UTF-8 BOM */ + goto again; + if (c < 0xF0) + return ((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2; + c3 = (soap_wchar)soap_get1(soap) & 0x3F; + if (c < 0xF8) + return ((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3; + c4 = (soap_wchar)soap_get1(soap) & 0x3F; + if (c < 0xFC) + return ((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4; + return ((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(soap_get1(soap) & 0x3F); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_puthex(struct soap *soap, const unsigned char *s, int n) +{ char d[2]; + register int i; +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { if (!(soap->dom->data = soap_s2hex(soap, s, NULL, n))) + return soap->error; + return SOAP_OK; + } +#endif + for (i = 0; i < n; i++) + { register int m = *s++; + d[0] = (char)((m >> 4) + (m > 159 ? '7' : '0')); + m &= 0x0F; + d[1] = (char)(m + (m > 9 ? '7' : '0')); + if (soap_send_raw(soap, d, 2)) + return soap->error; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +unsigned char* +SOAP_FMAC2 +soap_gethex(struct soap *soap, int *n) +{ +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { soap->dom->data = soap_string_in(soap, 0, -1, -1); + return (unsigned char*)soap_hex2s(soap, soap->dom->data, NULL, 0, n); + } +#endif +#ifdef WITH_FAST + soap->labidx = 0; + for (;;) + { register char *s; + register int i, k; + if (soap_append_lab(soap, NULL, 0)) + return NULL; + s = soap->labbuf + soap->labidx; + k = soap->lablen - soap->labidx; + soap->labidx = soap->lablen; + for (i = 0; i < k; i++) + { register char d1, d2; + register soap_wchar c; + c = soap_get(soap); + if (soap_isxdigit(c)) + { d1 = (char)c; + c = soap_get(soap); + if (soap_isxdigit(c)) + d2 = (char)c; + else + { soap->error = SOAP_TYPE; + return NULL; + } + } + else + { unsigned char *p; + soap_unget(soap, c); + if (n) + *n = (int)(soap->lablen - k + i); + p = (unsigned char*)soap_malloc(soap, soap->lablen - k + i); + if (p) + memcpy(p, soap->labbuf, soap->lablen - k + i); + return p; + } + *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'); + } + } +#else + if (soap_new_block(soap)) + return NULL; + for (;;) + { register int i; + register char *s = (char*)soap_push_block(soap, SOAP_BLKLEN); + if (!s) + { soap_end_block(soap); + return NULL; + } + for (i = 0; i < SOAP_BLKLEN; i++) + { register char d1, d2; + register soap_wchar c = soap_get(soap); + if (soap_isxdigit(c)) + { d1 = (char)c; + c = soap_get(soap); + if (soap_isxdigit(c)) + d2 = (char)c; + else + { soap_end_block(soap); + soap->error = SOAP_TYPE; + return NULL; + } + } + else + { unsigned char *p; + soap_unget(soap, c); + if (n) + *n = soap_size_block(soap, i); + p = (unsigned char*)soap_save_block(soap, NULL, 0); + return p; + } + *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'); + } + } +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putbase64(struct soap *soap, const unsigned char *s, int n) +{ register int i; + register unsigned long m; + char d[4]; + if (!s) + return SOAP_OK; +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { if (!(soap->dom->data = soap_s2base64(soap, s, NULL, n))) + return soap->error; + return SOAP_OK; + } +#endif + for (; n > 2; n -= 3, s += 3) + { m = s[0]; + m = (m << 8) | s[1]; + m = (m << 8) | s[2]; + for (i = 4; i > 0; m >>= 6) + d[--i] = soap_base64o[m & 0x3F]; + if (soap_send_raw(soap, d, 4)) + return soap->error; + } + if (n > 0) + { m = 0; + for (i = 0; i < n; i++) + m = (m << 8) | *s++; + for (; i < 3; i++) + m <<= 8; + for (i++; i > 0; m >>= 6) + d[--i] = soap_base64o[m & 0x3F]; + for (i = 3; i > n; i--) + d[i] = '='; + if (soap_send_raw(soap, d, 4)) + return soap->error; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +unsigned char* +SOAP_FMAC2 +soap_getbase64(struct soap *soap, int *n, int malloc_flag) +{ +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { soap->dom->data = soap_string_in(soap, 0, -1, -1); + return (unsigned char*)soap_base642s(soap, soap->dom->data, NULL, 0, n); + } +#endif +#ifdef WITH_FAST + soap->labidx = 0; + for (;;) + { register int i, k; + register char *s; + if (soap_append_lab(soap, NULL, 2)) + return NULL; + s = soap->labbuf + soap->labidx; + k = soap->lablen - soap->labidx; + soap->labidx = 3 * (soap->lablen / 3); + if (!s) + return NULL; + for (i = 0; i < k - 2; i += 3) + { register unsigned long m = 0; + register int j = 0; + do + { register soap_wchar c = soap_get(soap); + if (c == '=' || c < 0) + { unsigned char *p; + switch (j) + { case 2: + *s++ = (char)((m >> 4) & 0xFF); + i++; + break; + case 3: + *s++ = (char)((m >> 10) & 0xFF); + *s++ = (char)((m >> 2) & 0xFF); + i += 2; + } + if (n) + *n = (int)(soap->lablen - k + i); + p = (unsigned char*)soap_malloc(soap, soap->lablen - k + i); + if (p) + memcpy(p, soap->labbuf, soap->lablen - k + i); + if (c >= 0) + { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT) + ; + } + soap_unget(soap, c); + return p; + } + c -= '+'; + if (c >= 0 && c <= 79) + { int b = soap_base64i[c]; + if (b >= 64) + { soap->error = SOAP_TYPE; + return NULL; + } + m = (m << 6) + b; + j++; + } + else if (!soap_blank(c)) + { soap->error = SOAP_TYPE; + return NULL; + } + } while (j < 4); + *s++ = (char)((m >> 16) & 0xFF); + *s++ = (char)((m >> 8) & 0xFF); + *s++ = (char)(m & 0xFF); + } + } +#else + if (soap_new_block(soap)) + return NULL; + for (;;) + { register int i; + register char *s = (char*)soap_push_block(soap, 3 * SOAP_BLKLEN); /* must be multiple of 3 */ + if (!s) + { soap_end_block(soap); + return NULL; + } + for (i = 0; i < SOAP_BLKLEN; i++) + { register unsigned long m = 0; + register int j = 0; + do + { register soap_wchar c = soap_get(soap); + if (c == '=' || c < 0) + { unsigned char *p; + i *= 3; + switch (j) + { case 2: + *s++ = (char)((m >> 4) & 0xFF); + i++; + break; + case 3: + *s++ = (char)((m >> 10) & 0xFF); + *s++ = (char)((m >> 2) & 0xFF); + i += 2; + } + if (n) + *n = (int)soap_size_block(soap, i); + p = (unsigned char*)soap_save_block(soap, NULL, 0); + if (c >= 0) + { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT) + ; + } + soap_unget(soap, c); + return p; + } + c -= '+'; + if (c >= 0 && c <= 79) + { int b = soap_base64i[c]; + if (b >= 64) + { soap->error = SOAP_TYPE; + return NULL; + } + m = (m << 6) + b; + j++; + } + else if (!soap_blank(c)) + { soap->error = SOAP_TYPE; + return NULL; + } + } while (j < 4); + *s++ = (char)((m >> 16) & 0xFF); + *s++ = (char)((m >> 8) & 0xFF); + *s++ = (char)(m & 0xFF); + } + } +#endif +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_xop_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options) +{ /* Check MTOM xop:Include element (within hex/base64Binary) */ + /* TODO: this code to be obsoleted with new import/xop.h conventions */ + int body = soap->body; /* should save type too? */ + if (!soap_peek_element(soap)) + { if (!soap_element_begin_in(soap, "xop:Include", 0, NULL) && *soap->href) + { if (soap_dime_forward(soap, ptr, size, id, type, options)) + return soap->error; + } + if (soap->body && soap_element_end_in(soap, NULL)) + return soap->error; + } + soap->body = body; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_dime_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options) +{ struct soap_xlist *xp = (struct soap_xlist*)SOAP_MALLOC(soap, sizeof(struct soap_xlist)); + *ptr = NULL; + *size = 0; + *id = soap_strdup(soap, soap->href); + *type = NULL; + *options = NULL; + if (!xp) + return soap->error = SOAP_EOM; + xp->next = soap->xlist; + xp->ptr = ptr; + xp->size = size; + xp->id = *id; + xp->type = type; + xp->options = options; + soap->xlist = xp; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_strdup(struct soap *soap, const char *s) +{ char *t = NULL; + if (s && (t = (char*)soap_malloc(soap, strlen(s) + 1))) + strcpy(t, s); + return t; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_new_block(struct soap *soap) +{ struct soap_blist *p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New block sequence (prev=%p)\n", soap->blist)); + if (!(p = (struct soap_blist*)SOAP_MALLOC(soap, sizeof(struct soap_blist)))) + return SOAP_EOM; + p->next = soap->blist; + p->ptr = NULL; + p->size = 0; + soap->blist = p; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_push_block(struct soap *soap, size_t n) +{ char *p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push block of %u bytes (%u bytes total)\n", (unsigned int)n, (unsigned int)soap->blist->size + (unsigned int)n)); + if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(char*) + sizeof(size_t)))) + { soap->error = SOAP_EOM; + return NULL; + } + *(char**)p = soap->blist->ptr; + *(size_t*)(p + sizeof(char*)) = n; + soap->blist->ptr = p; + soap->blist->size += n; + return p + sizeof(char*) + sizeof(size_t); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_pop_block(struct soap *soap) +{ char *p; + if (!soap->blist->ptr) + return; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop block\n")); + p = soap->blist->ptr; + soap->blist->size -= *(size_t*)(p + sizeof(char*)); + soap->blist->ptr = *(char**)p; + SOAP_FREE(soap, p); +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static void +soap_update_ptrs(struct soap *soap, char *start, char *end, char *p1, char *p2) +{ int i; + register struct soap_ilist *ip; + register struct soap_flist *fp; +#ifndef WITH_LEANER + register struct soap_xlist *xp; +#endif + register void *p, **q; + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { if (ip->ptr && (char*)ip->ptr >= start && (char*)ip->ptr < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", ip->id, ip->ptr, (char*)ip->ptr + (p1-p2))); + ip->ptr = (char*)ip->ptr + (p1-p2); + } + for (q = &ip->link; q; q = (void**)p) + { p = *q; + if (p && (char*)p >= start && (char*)p < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Link update id='%s' %p\n", ip->id, p)); + *q = (char*)p + (p1-p2); + } + } + for (q = &ip->copy; q; q = (void**)p) + { p = *q; + if (p && (char*)p >= start && (char*)p < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy chain update id='%s' %p\n", ip->id, p)); + *q = (char*)p + (p1-p2); + } + } + for (fp = ip->flist; fp; fp = fp->next) + { if ((char*)fp->ptr >= start && (char*)fp->ptr < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy list update id='%s' %p\n", ip->id, fp)); + fp->ptr = (char*)fp->ptr + (p1-p2); + } + } + } + } +#ifndef WITH_LEANER + for (xp = soap->xlist; xp; xp = xp->next) + { if (xp->ptr && (char*)xp->ptr >= start && (char*)xp->ptr < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", xp->id?xp->id:"", xp->ptr, (char*)xp->ptr + (p1-p2))); + xp->ptr = (unsigned char**)((char*)xp->ptr + (p1-p2)); + xp->size = (int*)((char*)xp->size + (p1-p2)); + xp->type = (char**)((char*)xp->type + (p1-p2)); + xp->options = (char**)((char*)xp->options + (p1-p2)); + } + } +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static int +soap_has_copies(struct soap *soap, register const char *start, register const char *end) +{ register int i; + register struct soap_ilist *ip; + register struct soap_flist *fp; + register const char *p; + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { for (p = (const char*)ip->copy; p; p = *(const char**)p) + if (p >= start && p < end) + return SOAP_ERR; + for (fp = ip->flist; fp; fp = fp->next) + if ((const char*)fp->ptr >= start && (const char*)fp->ptr < end) + return SOAP_ERR; + } + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_resolve(struct soap *soap) +{ register int i; + register struct soap_ilist *ip; + register struct soap_flist *fp; + short flag; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data\n")); + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { if (ip->ptr) + { register void *p, **q, *r; + q = (void**)ip->link; + ip->link = NULL; + r = ip->ptr; + DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing link chain to resolve id='%s'\n", ip->id)); + while (q) + { p = *q; + *q = r; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "... link %p -> %p\n", q, r)); + q = (void**)p; + } + } + else if (*ip->id == '#') + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Missing data for id='%s'\n", ip->id)); + strcpy(soap->id, ip->id + 1); + return soap->error = SOAP_MISSING_ID; + } + } + } + do + { flag = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution phase\n")); + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { if (ip->ptr && !soap_has_copies(soap, (const char*)ip->ptr, (const char*)ip->ptr + ip->size)) + { if (ip->copy) + { register void *p, **q = (void**)ip->copy; + DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing copy chain to resolve id='%s'\n", ip->id)); + ip->copy = NULL; + do + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... copy %p -> %p (%u bytes)\n", ip->ptr, q, (unsigned int)ip->size)); + p = *q; + memcpy(q, ip->ptr, ip->size); + q = (void**)p; + } while (q); + flag = 1; + } + for (fp = ip->flist; fp; fp = ip->flist) + { register unsigned int k = fp->level; + register void *p = ip->ptr; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data type=%d location=%p level=%u,%u id='%s'\n", ip->type, p, ip->level, fp->level, ip->id)); + while (ip->level < k) + { register void **q = (void**)soap_malloc(soap, sizeof(void*)); + if (!q) + return soap->error; + *q = p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level, new location=%p holds=%p...\n", q, *q)); + p = (void*)q; + k--; + } + if (fp->fcopy) + fp->fcopy(soap, ip->type, fp->type, fp->ptr, fp->len, p, ip->size); + else + soap_fcopy(soap, ip->type, fp->type, fp->ptr, fp->len, p, ip->size); + ip->flist = fp->next; + SOAP_FREE(soap, fp); + flag = 1; + } + } + } + } + } while (flag); +#ifdef SOAP_DEBUG + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { if (ip->copy || ip->flist) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution error: forwarded data for id='%s' could not be propagated, please report this problem to the developers\n", ip->id)); + } + } + } +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution done\n")); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_size_block(struct soap *soap, size_t n) +{ if (soap->blist->ptr) + { soap->blist->size -= *(size_t*)(soap->blist->ptr + sizeof(char*)) - n; + *(size_t*)(soap->blist->ptr + sizeof(char*)) = n; + } + return soap->blist->size; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_first_block(struct soap *soap) +{ char *p, *q, *r; + p = soap->blist->ptr; + if (!p) + return NULL; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "First block\n")); + r = NULL; + do + { q = *(char**)p; + *(char**)p = r; + r = p; + p = q; + } while (p); + soap->blist->ptr = r; + return r + sizeof(char*) + sizeof(size_t); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_next_block(struct soap *soap) +{ char *p; + p = soap->blist->ptr; + if (p) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Next block\n")); + soap->blist->ptr = *(char**)p; + SOAP_FREE(soap, p); + if (soap->blist->ptr) + return soap->blist->ptr + sizeof(char*) + sizeof(size_t); + } + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_block_size(struct soap *soap) +{ return *(size_t*)(soap->blist->ptr + sizeof(char*)); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_end_block(struct soap *soap) +{ struct soap_blist *bp; + char *p, *q; + bp = soap->blist; + if (bp) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of block sequence, free all remaining blocks\n")); + for (p = bp->ptr; p; p = q) + { q = *(char**)p; + SOAP_FREE(soap, p); + } + soap->blist = bp->next; + SOAP_FREE(soap, bp); + } + DBGLOG(TEST, if (soap->blist) SOAP_MESSAGE(fdebug, "Restore previous block sequence\n")); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_save_block(struct soap *soap, char *p, int flag) +{ register size_t n; + register char *q, *s; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Save all blocks in contiguous memory space of %u bytes (%p->%p)\n", (unsigned int)soap->blist->size, soap->blist->ptr, p)); + if (soap->blist->size) + { if (!p) + p = (char*)soap_malloc(soap, soap->blist->size); + if (p) + { for (s = p, q = soap_first_block(soap); q; q = soap_next_block(soap)) + { n = soap_block_size(soap); +#ifndef WITH_NOIDREF + if (flag) + soap_update_ptrs(soap, q, q + n, s, q); +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy %u bytes from %p to %p\n", (unsigned int)n, q, s)); + memcpy(s, q, n); + s += n; + } + } + else + soap->error = SOAP_EOM; + } + soap_end_block(soap); + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putsize(struct soap *soap, const char *type, int size) +{ return soap_putsizes(soap, type, &size, 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putsizes(struct soap *soap, const char *type, const int *size, int dim) +{ return soap_putsizesoffsets(soap, type, size, NULL, dim); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putsizesoffsets(struct soap *soap, const char *type, const int *size, const int *offset, int dim) +{ int i; + if (!type) + return NULL; + if (soap->version == 2) + { sprintf(soap->type, "%s[%d", type, size[0]); + for (i = 1; i < dim; i++) + sprintf(soap->type + strlen(soap->type), " %d", size[i]); + } + else + { if (offset) + { sprintf(soap->type, "%s[%d", type, size[0] + offset[0]); + for (i = 1; i < dim; i++) + sprintf(soap->type + strlen(soap->type), ",%d", size[i] + offset[i]); + } + else + { sprintf(soap->type, "%s[%d", type, size[0]); + for (i = 1; i < dim; i++) + sprintf(soap->type + strlen(soap->type), ",%d", size[i]); + } + strcat(soap->type, "]"); + } + return soap->type; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putoffset(struct soap *soap, int offset) +{ return soap_putoffsets(soap, &offset, 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putoffsets(struct soap *soap, const int *offset, int dim) +{ register int i; + sprintf(soap->arrayOffset, "[%d", offset[0]); + for (i = 1; i < dim; i++) + sprintf(soap->arrayOffset + strlen(soap->arrayOffset), ",%d", offset[i]); + strcat(soap->arrayOffset, "]"); + return soap->arrayOffset; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_size(const int *size, int dim) +{ register int i, n = size[0]; + for (i = 1; i < dim; i++) + n *= size[i]; + return n; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getoffsets(const char *attr, const int *size, int *offset, int dim) +{ register int i, j = 0; + if (offset) + for (i = 0; i < dim && attr && *attr; i++) + { attr++; + j *= size[i]; + j += offset[i] = (int)atol(attr); + attr = strchr(attr, ','); + } + else + for (i = 0; i < dim && attr && *attr; i++) + { attr++; + j *= size[i]; + j += (int)atol(attr); + attr = strchr(attr, ','); + } + return j; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getsize(const char *attr1, const char *attr2, int *j) +{ register int n, k; + char *s; + *j = 0; + if (!*attr1) + return -1; + if (*attr1 == '[') + attr1++; + n = 1; + for (;;) + { k = (int)soap_strtol(attr1, &s, 10); + n *= k; + if (k < 0 || n > SOAP_MAXARRAYSIZE || s == attr1) + return -1; + attr1 = strchr(s, ','); + if (!attr1) + attr1 = strchr(s, ' '); + if (attr2 && *attr2) + { attr2++; + *j *= k; + k = (int)soap_strtol(attr2, &s, 10); + *j += k; + if (k < 0) + return -1; + attr2 = s; + } + if (!attr1) + break; + attr1++; + } + return n - *j; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getsizes(const char *attr, int *size, int dim) +{ register int i, k, n; + if (!*attr) + return -1; + i = strlen(attr); + n = 1; + do + { for (i = i-1; i >= 0; i--) + if (attr[i] == '[' || attr[i] == ',' || attr[i] == ' ') + break; + k = (int)atol(attr + i + 1); + n *= size[--dim] = k; + if (k < 0 || n > SOAP_MAXARRAYSIZE) + return -1; + } while (i >= 0 && attr[i] != '['); + return n; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getposition(const char *attr, int *pos) +{ register int i, n; + if (!*attr) + return -1; + n = 0; + i = 1; + do + { pos[n++] = (int)atol(attr + i); + while (attr[i] && attr[i] != ',' && attr[i] != ']') + i++; + if (attr[i] == ',') + i++; + } while (n < SOAP_MAXDIMS && attr[i] && attr[i] != ']'); + return n; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_push_namespace(struct soap *soap, const char *id, const char *ns) +{ register struct soap_nlist *np; + register struct Namespace *p; + register short i = -1; + register size_t n, k; + n = strlen(id); + k = strlen(ns) + 1; + p = soap->local_namespaces; + if (p) + { for (i = 0; p->id; p++, i++) + { if (p->ns && !strcmp(ns, p->ns)) + { if (p->out) + { SOAP_FREE(soap, p->out); + p->out = NULL; + } + break; + } + if (p->out) + { if (!strcmp(ns, p->out)) + break; + } + else if (p->in) + { if (!soap_tag_cmp(ns, p->in)) + { if ((p->out = (char*)SOAP_MALLOC(soap, k))) + strcpy(p->out, ns); + break; + } + } + } + if (!p || !p->id) + i = -1; + } + if (i >= 0) + k = 0; + np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k); + if (!np) + return soap->error = SOAP_EOM; + np->next = soap->nlist; + soap->nlist = np; + np->level = soap->level; + np->index = i; + strcpy(np->id, id); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push namespace binding (level=%u) '%s' '%s'\n", soap->level, id, ns)); + if (i < 0) + { np->ns = np->id + n + 1; + strcpy(np->ns, ns); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push NOT OK: no match found for '%s' in namespace mapping table (added to stack anyway)\n", ns)); + } + else + { np->ns = NULL; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push OK ('%s' matches '%s' in namespace table)\n", id, p->id)); + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_pop_namespace(struct soap *soap) +{ register struct soap_nlist *np; + while (soap->nlist && soap->nlist->level >= soap->level) + { np = soap->nlist->next; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Popped namespace binding (level=%u) '%s'\n", soap->level, soap->nlist->id)); + SOAP_FREE(soap, soap->nlist); + soap->nlist = np; + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_match_namespace(struct soap *soap, const char *id1, const char *id2, int n1, int n2) +{ register struct soap_nlist *np = soap->nlist; + while (np && (strncmp(np->id, id1, n1) || np->id[n1])) + np = np->next; + if (np) + { if (np->index < 0 + || (soap->local_namespaces[np->index].id + && (strncmp(soap->local_namespaces[np->index].id, id2, n2) + || soap->local_namespaces[np->index].id[n2]))) + return SOAP_NAMESPACE; + return SOAP_OK; + } + if (n1 == 3 && n1 == n2 && !strcmp(id1, "xml") && !strcmp(id1, id2)) + return SOAP_OK; + return SOAP_SYNTAX_ERROR; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_current_namespace(struct soap *soap, const char *tag) +{ register struct soap_nlist *np; + register const char *s; + np = soap->nlist; + if (!(s = strchr(tag, ':'))) + { while (np && *np->id) /* find default namespace, if present */ + np = np->next; + } + else + { while (np && (strncmp(np->id, tag, s - tag) || np->id[s - tag])) + np = np->next; + if (!np) + soap->error = SOAP_NAMESPACE; + } + if (np) + { if (np->index >= 0) + return soap->namespaces[np->index].ns; + if (np->ns) + return soap_strdup(soap, np->ns); + } + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_tag_cmp(const char *s, const char *t) +{ for (;;) + { register int c1 = *s; + register int c2 = *t; + if (!c1 || c1 == '"') + break; + if (c2 != '-') + { if (c1 != c2) + { if (c1 >= 'A' && c1 <= 'Z') + c1 += 'a' - 'A'; + if (c2 >= 'A' && c2 <= 'Z') + c2 += 'a' - 'A'; + } + if (c1 != c2) + { if (c2 != '*') + return 1; + c2 = *++t; + if (!c2) + return 0; + if (c2 >= 'A' && c2 <= 'Z') + c2 += 'a' - 'A'; + for (;;) + { c1 = *s; + if (!c1 || c1 == '"') + break; + if (c1 >= 'A' && c1 <= 'Z') + c1 += 'a' - 'A'; + if (c1 == c2 && !soap_tag_cmp(s + 1, t + 1)) + return 0; + s++; + } + break; + } + } + s++; + t++; + } + if (*t == '*' && !t[1]) + return 0; + return *t; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_match_tag(struct soap *soap, const char *tag1, const char *tag2) +{ register const char *s, *t; + if (!tag1 || !tag2 || !*tag2) + return SOAP_OK; + s = strchr(tag1, ':'); + t = strchr(tag2, ':'); + if (t) + { if (s) + { if (t[1] && SOAP_STRCMP(s + 1, t + 1)) + return SOAP_TAG_MISMATCH; + if (t != tag2 && soap_match_namespace(soap, tag1, tag2, s - tag1, t - tag2)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2)); + return SOAP_TAG_MISMATCH; + } + } + else if (SOAP_STRCMP(tag1, t + 1)) + return SOAP_TAG_MISMATCH; + else if (t != tag2 && soap_match_namespace(soap, tag1, tag2, 0, t - tag2)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2)); + return SOAP_TAG_MISMATCH; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags and (default) namespaces match: '%s' '%s'\n", tag1, tag2)); + return SOAP_OK; + } + if (s) + { if (SOAP_STRCMP(s + 1, tag2)) + return SOAP_TAG_MISMATCH; + } + else if (SOAP_STRCMP(tag1, tag2)) + return SOAP_TAG_MISMATCH; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags match: '%s' '%s'\n", tag1, tag2)); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_match_array(struct soap *soap, const char *type) +{ if (*soap->arrayType) + if (soap_match_tag(soap, soap->arrayType, type) + && soap_match_tag(soap, soap->arrayType, "xsd:anyType") + && soap_match_tag(soap, soap->arrayType, "xsd:ur-type") + ) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array type mismatch: '%s' '%s'\n", soap->arrayType, type)); + return SOAP_TAG_MISMATCH; + } + return SOAP_OK; +} +#endif + +/******************************************************************************\ + * + * SSL + * +\******************************************************************************/ + +#ifdef WITH_OPENSSL +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_rand() +{ unsigned char buf[4]; + if (!ssl_init_done) + soap_ssl_init(); + RAND_pseudo_bytes(buf, 4); + return *(int*)buf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_ssl_server_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *password, const char *cafile, const char *capath, const char *dhfile, const char *randfile, const char *sid) +{ int err; + soap->keyfile = keyfile; + soap->password = password; + soap->cafile = cafile; + soap->capath = capath; + soap->dhfile = dhfile; + soap->randfile = randfile; + soap->ssl_flags = flags | (dhfile == NULL ? SOAP_SSL_RSA : 0); + if (!(err = soap->fsslauth(soap))) + { if (sid) + SSL_CTX_set_session_id_context(soap->ctx, (unsigned char*)sid, strlen(sid)); + } + return err; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_ssl_client_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *password, const char *cafile, const char *capath, const char *randfile) +{ soap->keyfile = keyfile; + soap->password = password; + soap->cafile = cafile; + soap->capath = capath; + soap->dhfile = NULL; + soap->ssl_flags = flags; + soap->randfile = randfile; + return soap->fsslauth(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_ssl_init() +{ /* Note: for MT systems, the main program MUST call soap_ssl_init() before any threads are started */ + if (!ssl_init_done) + { ssl_init_done = 1; + SSL_library_init(); +#ifndef WITH_LEAN + SSL_load_error_strings(); +#endif + if (!RAND_load_file("/dev/urandom", 1024)) + { char buf[1024]; + RAND_seed(buf, sizeof(buf)); + while (!RAND_status()) + { int r = rand(); + RAND_seed(&r, sizeof(int)); + } + } + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +const char * +SOAP_FMAC2 +soap_ssl_error(struct soap *soap, int ret) +{ int err = SSL_get_error(soap->ssl, ret); + const char *msg = soap_code_str(h_ssl_error_codes, err); + if (msg) + strcpy(soap->msgbuf, msg); + else + return ERR_error_string(err, soap->msgbuf); + if (ERR_peek_error()) + { unsigned long r; + strcat(soap->msgbuf, "\n"); + while ((r = ERR_get_error())) + ERR_error_string_n(r, soap->msgbuf + strlen(soap->msgbuf), sizeof(soap->msgbuf) - strlen(soap->msgbuf)); + } + else + { switch (ret) + { case 0: + strcpy(soap->msgbuf, "EOF was observed that violates the protocol. The client probably provided invalid authentication information."); + break; + case -1: + sprintf(soap->msgbuf, "Error observed by underlying BIO: %s", strerror(errno)); + break; + } + } + return soap->msgbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +ssl_password(char *buf, int num, int rwflag, void *userdata) +{ if (num < (int)strlen((char*)userdata) + 1) + return 0; + return strlen(strcpy(buf, (char*)userdata)); +} +#endif + +/******************************************************************************/ +/* This callback is included for future references. It should not be deleted +#ifndef PALM_2 +static DH * +ssl_tmp_dh(SSL *ssl, int is_export, int keylength) +{ static DH *dh512 = NULL; + static DH *dh1024 = NULL; + DH *dh; + switch (keylength) + { case 512: + if (!dh512) + { BIO *bio = BIO_new_file("dh512.pem", "r"); + if (bio) + { dh512 = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + return dh512; + } + } + else + return dh512; + default: + if (!dh1024) + { BIO *bio = BIO_new_file("dh1024.pem", "r"); + if (bio) + { dh1024 = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + } + } + dh = dh1024; + } + return dh; +} +#endif +*/ + +/******************************************************************************/ +#ifndef PALM_1 +static int +ssl_auth_init(struct soap *soap) +{ long flags; + int mode; + if (!ssl_init_done) + soap_ssl_init(); + if (!soap->ctx) + { if (!(soap->ctx = SSL_CTX_new(SSLv23_method()))) + return soap_set_receiver_error(soap, "SSL error", "Can't setup context", SOAP_SSL_ERROR); + } + if (soap->randfile) + { if (!RAND_load_file(soap->randfile, -1)) + return soap_set_receiver_error(soap, "SSL error", "Can't load randomness", SOAP_SSL_ERROR); + } + if (soap->cafile || soap->capath) + { if (!SSL_CTX_load_verify_locations(soap->ctx, soap->cafile, soap->capath)) + return soap_set_receiver_error(soap, "SSL error", "Can't read CA file and directory", SOAP_SSL_ERROR); + if (soap->cafile && (soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION)) + SSL_CTX_set_client_CA_list(soap->ctx, SSL_load_client_CA_file(soap->cafile)); + } + if (!SSL_CTX_set_default_verify_paths(soap->ctx)) + return soap_set_receiver_error(soap, "SSL error", "Can't read default CA file and/or directory", SOAP_SSL_ERROR); +/* This code assumes a typical scenario, see alternative code below */ + if (soap->keyfile) + { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile)) + return soap_set_receiver_error(soap, "SSL error", "Can't read certificate key file", SOAP_SSL_ERROR); + if (soap->password) + { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password); + SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password); + } + if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM)) + return soap_set_receiver_error(soap, "SSL error", "Can't read key file", SOAP_SSL_ERROR); + } +/* Suggested alternative approach to check cafile first before the key file: + if (soap->password) + { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password); + SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password); + } + if (!soap->cafile || !SSL_CTX_use_certificate_chain_file(soap->ctx, soap->cafile)) + { if (soap->keyfile) + { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile)) + return soap_set_receiver_error(soap, "SSL error", "Can't read certificate or key file", SOAP_SSL_ERROR); + if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM)) + return soap_set_receiver_error(soap, "SSL error", "Can't read key file", SOAP_SSL_ERROR); + } + } +*/ + if ((soap->ssl_flags & SOAP_SSL_RSA)) + { RSA *rsa = RSA_generate_key(1024, RSA_F4, NULL, NULL); + if (!SSL_CTX_set_tmp_rsa(soap->ctx, rsa)) + { if (rsa) + RSA_free(rsa); + return soap_set_receiver_error(soap, "SSL error", "Can't set RSA key", SOAP_SSL_ERROR); + } + RSA_free(rsa); + } + else if (soap->dhfile) + { DH *dh = 0; + BIO *bio; + bio = BIO_new_file(soap->dhfile, "r"); + if (!bio) + return soap_set_receiver_error(soap, "SSL error", "Can't read DH file", SOAP_SSL_ERROR); + dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + if (SSL_CTX_set_tmp_dh(soap->ctx, dh) < 0) + { if (dh) + DH_free(dh); + return soap_set_receiver_error(soap, "SSL error", "Can't set DH parameters", SOAP_SSL_ERROR); + } + DH_free(dh); + } + flags = (SSL_OP_ALL | SSL_OP_NO_SSLv2); + if ((soap->ssl_flags & SOAP_SSLv3)) + flags |= SSL_OP_NO_TLSv1; + if ((soap->ssl_flags & SOAP_TLSv1)) + flags |= SSL_OP_NO_SSLv3; + SSL_CTX_set_options(soap->ctx, flags); + if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION)) + mode = (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT); + else if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION)) + mode = SSL_VERIFY_PEER; + else + mode = SSL_VERIFY_NONE; + SSL_CTX_set_verify(soap->ctx, mode, soap->fsslverify); +#if (OPENSSL_VERSION_NUMBER < 0x00905100L) + SSL_CTX_set_verify_depth(soap->ctx, 1); +#else + SSL_CTX_set_verify_depth(soap->ctx, 9); +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +ssl_verify_callback(int ok, X509_STORE_CTX *store) +{ +#ifdef SOAP_DEBUG + if (!ok) + { char data[256]; + X509 *cert = X509_STORE_CTX_get_current_cert(store); + fprintf(stderr, "SSL verify error or warning with certificate at depth %d: %s\n", X509_STORE_CTX_get_error_depth(store), X509_verify_cert_error_string(X509_STORE_CTX_get_error(store))); + X509_NAME_oneline(X509_get_issuer_name(cert), data, sizeof(data)); + fprintf(stderr, "certificate issuer %s\n", data); + X509_NAME_oneline(X509_get_subject_name(cert), data, sizeof(data)); + fprintf(stderr, "certificate subject %s\n", data); + } +#endif + /* Note: return 1 to continue, but unsafe progress will be terminated by SSL */ + return ok; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_ssl_accept(struct soap *soap) +{ BIO *bio; + int i, r; + if (!soap_valid_socket(soap->socket)) + return soap_set_receiver_error(soap, "SSL error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR); + if (!soap->ctx && (soap->error = soap->fsslauth(soap))) + return SOAP_INVALID_SOCKET; + if (!soap->ssl) + { soap->ssl = SSL_new(soap->ctx); + if (!soap->ssl) + return soap_set_receiver_error(soap, "SSL error", "SSL_new() failed in soap_ssl_accept()", SOAP_SSL_ERROR); + } + else + SSL_clear(soap->ssl); + soap->imode |= SOAP_ENC_SSL; + soap->omode |= SOAP_ENC_SSL; +#if defined(WIN32) + { u_long nonblocking = 1; + ioctlsocket((SOAP_SOCKET)soap->socket, FIONBIO, &nonblocking); + } +#elif defined(VXWORKS) + { u_long nonblocking = 1; + ioctl((SOAP_SOCKET)soap->socket, FIONBIO, (int)&nonblocking); + } +#else + fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL)|O_NONBLOCK); +#endif + bio = BIO_new_socket((SOAP_SOCKET)soap->socket, BIO_NOCLOSE); + SSL_set_bio(soap->ssl, bio, bio); + i = 100; /* 100 * 0.1 ms retries */ + while ((r = SSL_accept(soap->ssl)) <= 0) + { int err = SSL_get_error(soap->ssl, r); + if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) + { struct timeval timeout; + fd_set fd; + if (i-- <= 0) + break; + timeout.tv_sec = 0; + timeout.tv_usec = 100000; +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + return SOAP_FD_EXCEEDED; /* Hint: MUST increase FD_SETSIZE */ +#endif + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->socket, &fd); + r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout); + if (r < 0 && (r = soap_socket_errno(soap->socket)) != SOAP_EINTR) + { soap->errnum = r; + return SOAP_EOF; + } + } + else + { soap->errnum = err; + break; + } + } +#if defined(WIN32) + { u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)soap->socket, FIONBIO, &blocking); + } +#elif defined(VXWORKS) + { u_long blocking = 0; + ioctl((SOAP_SOCKET)soap->socket, FIONBIO, (int)&blocking); + } +#else + fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL)&~O_NONBLOCK); +#endif + if (r <= 0) + { soap_set_receiver_error(soap, soap_ssl_error(soap, r), "SSL_accept() failed in soap_ssl_accept()", SOAP_SSL_ERROR); + soap_closesock(soap); + return SOAP_SSL_ERROR; + } + if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION)) + { X509 *peer; + int err; + if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK) + { soap_closesock(soap); + return soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL certificate presented by peer cannot be verified in soap_ssl_accept()", SOAP_SSL_ERROR); + } + peer = SSL_get_peer_certificate(soap->ssl); + if (!peer) + { soap_closesock(soap); + return soap_set_sender_error(soap, "SSL error", "No SSL certificate was presented by the peer in soap_ssl_accept()", SOAP_SSL_ERROR); + } + X509_free(peer); + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#endif /* WITH_OPENSSL */ + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_init(struct soap *soap) +{ soap->errmode = 1; +#ifdef WIN32 + if (tcp_done) + return 0; + else + { WSADATA w; + if (WSAStartup(MAKEWORD(1, 1), &w)) + return -1; + tcp_done = 1; + } +#endif + return 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_done(struct soap *soap) +{ +#ifdef SOAP_DEBUG + int i; +#endif + if (soap_check_state(soap)) + return; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Done with context\n")); + soap_free_temp(soap); + while (soap->clist) + { struct soap_clist *p = soap->clist->next; + SOAP_FREE(soap, soap->clist); + soap->clist = p; + } + soap->keep_alive = 0; /* to force close the socket */ + soap_closesock(soap); +#ifdef WITH_COOKIES + soap_free_cookies(soap); +#endif + while (soap->plugins) + { register struct soap_plugin *p = soap->plugins->next; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Removing plugin '%s'\n", soap->plugins->id)); + if (soap->plugins->fcopy || soap->state == SOAP_INIT) + soap->plugins->fdelete(soap, soap->plugins); + SOAP_FREE(soap, soap->plugins); + soap->plugins = p; + } + soap->fplugin = fplugin; + soap->fmalloc = NULL; +#ifndef WITH_NOHTTP + soap->fpost = http_post; + soap->fget = http_get; + soap->fform = NULL; + soap->fposthdr = http_post_header; + soap->fresponse = http_response; + soap->fparse = http_parse; + soap->fparsehdr = http_parse_header; +#endif + soap->fheader = NULL; +#ifndef WITH_NOIO +#ifndef WITH_IPV6 + soap->fresolve = tcp_gethost; +#else + soap->fresolve = NULL; +#endif + soap->faccept = tcp_accept; + soap->fopen = tcp_connect; + soap->fclose = tcp_disconnect; + soap->fclosesocket = tcp_closesocket; + soap->fshutdownsocket = tcp_shutdownsocket; + soap->fsend = fsend; + soap->frecv = frecv; + soap->fpoll = soap_poll; +#else + soap->fopen = NULL; + soap->fclose = NULL; + soap->fpoll = NULL; +#endif +#ifndef WITH_LEANER + soap->fprepareinit = NULL; + soap->fpreparesend = NULL; + soap->fpreparerecv = NULL; + soap->fpreparefinal = NULL; +#endif + soap->fseterror = NULL; + soap->fignore = NULL; + soap->fserveloop = NULL; +#ifdef WITH_OPENSSL + if (soap->session) + { SSL_SESSION_free(soap->session); + soap->session = NULL; + } +#endif + if (soap->state == SOAP_INIT) + { if (soap_valid_socket(soap->master)) + { soap->fclosesocket(soap, (SOAP_SOCKET)soap->master); + soap->master = SOAP_INVALID_SOCKET; + } +#ifdef WITH_OPENSSL + if (soap->ctx) + { SSL_CTX_free(soap->ctx); + soap->ctx = NULL; + } +#endif + } +#ifdef SOAP_DEBUG + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free logfiles\n")); + for (i = 0; i < SOAP_MAXLOGS; i++) + { if (soap->logfile[i]) + { SOAP_FREE(soap, (void*)soap->logfile[i]); + soap->logfile[i] = NULL; + } + soap_close_logfile(soap, i); + } + soap_free_mht(soap); + soap->state = 0; +#endif +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_cleanup(struct soap *soap) +{ soap_done(soap); +#ifdef WIN32 + if (!tcp_done) + return; + tcp_done = 0; + WSACleanup(); +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static const char* +tcp_error(struct soap *soap) +{ register const char *msg = NULL; + switch (soap->errmode) + { case 0: + msg = soap_strerror(soap); + break; + case 1: + msg = "WSAStartup failed"; + break; + case 2: + { +#ifndef WITH_LEAN + msg = soap_code_str(h_error_codes, soap->errnum); + if (!msg) +#endif + { sprintf(soap->msgbuf, "TCP/UDP IP error %d", soap->errnum); + msg = soap->msgbuf; + } + } + } + return msg; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static const char* +http_error(struct soap *soap, int status) +{ register const char *msg = SOAP_STR_EOS; +#ifndef WITH_LEAN + msg = soap_code_str(h_http_error_codes, status); + if (!msg) + msg = SOAP_STR_EOS; +#endif + return msg; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_IPV6 +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_gethost(struct soap *soap, const char *addr, struct in_addr *inaddr) +{ soap_int32 iadd = -1; + struct hostent hostent, *host = &hostent; +#ifdef VXWORKS + int hostint; + /* inet_addr(), and hostGetByName() expect "char *"; addr is a "const char *". */ + iadd = inet_addr((char*)addr); +#else +#if defined(_AIXVERSION_431) || defined(TRU64) + struct hostent_data ht_data; +#endif +#ifdef AS400 + iadd = inet_addr((void*)addr); +#else + iadd = inet_addr(addr); +#endif +#endif + if (iadd != -1) + { memcpy(inaddr, &iadd, sizeof(iadd)); + return SOAP_OK; + } +#if defined(__GLIBC__) + if (gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &host, &soap->errnum) < 0) + host = NULL; +#elif defined(_AIXVERSION_431) || defined(TRU64) + memset((void*)&ht_data, 0, sizeof(ht_data)); + if (gethostbyname_r(addr, &hostent, &ht_data) < 0) + { host = NULL; + soap->errnum = h_errno; + } +#elif defined(HAVE_GETHOSTBYNAME_R) + host = gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &soap->errnum); +#elif defined(VXWORKS) + /* If the DNS resolver library resolvLib has been configured in the vxWorks + * image, a query for the host IP address is sent to the DNS server, if the + * name was not found in the local host table. */ + hostint = hostGetByName((char*)addr); + if (hostint == ERROR) + { host = NULL; + soap->errnum = soap_errno; + } +#else +#ifdef AS400 + if (!(host = gethostbyname((void*)addr))) + soap->errnum = h_errno; +#else + if (!(host = gethostbyname(addr))) + soap->errnum = h_errno; +#endif +#endif + if (!host) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Host name not found\n")); + return SOAP_ERR; + } +#ifdef VXWORKS + inaddr->s_addr = hostint; +#else + memcpy(inaddr, host->h_addr, host->h_length); +#endif + return SOAP_OK; +} +#endif +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_connect(struct soap *soap, const char *endpoint, const char *host, int port) +{ +#ifdef WITH_IPV6 + struct addrinfo hints, *res, *ressave; +#endif + register int err, fd; +#ifndef WITH_LEAN + int len = SOAP_BUFLEN; + int set = 1; +#endif + if (soap_valid_socket(soap->socket)) + soap->fclosesocket(soap, (SOAP_SOCKET)soap->socket); + soap->socket = SOAP_INVALID_SOCKET; + if (tcp_init(soap)) + { soap->errnum = 0; + soap_set_sender_error(soap, tcp_error(soap), "TCP init failed in tcp_connect()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + soap->errmode = 0; +#ifdef WITH_IPV6 + memset((void*)&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + hints.ai_socktype = SOCK_DGRAM; + else +#endif + hints.ai_socktype = SOCK_STREAM; + soap->errmode = 2; + if (soap->proxy_host) + err = getaddrinfo(soap->proxy_host, soap_int2s(soap, soap->proxy_port), &hints, &res); + else + err = getaddrinfo(host, soap_int2s(soap, port), &hints, &res); + if (err) + { soap_set_sender_error(soap, gai_strerror(err), "getaddrinfo failed in tcp_connect()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + ressave = res; +again: + fd = (int)socket(res->ai_family, res->ai_socktype, res->ai_protocol); + soap->errmode = 0; +#else +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + fd = (int)socket(AF_INET, SOCK_DGRAM, 0); + else +#endif + fd = (int)socket(AF_INET, SOCK_STREAM, 0); +#endif + if (fd < 0) + { soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "socket failed in tcp_connect()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#ifdef SOCKET_CLOSE_ON_EXEC +#ifdef WIN32 +#ifndef UNDER_CE + SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0); +#endif +#else + fcntl(fd, F_SETFD, 1); +#endif +#endif +#ifndef WITH_LEAN + if (soap->connect_flags == SO_LINGER) + { struct linger linger; + memset((void*)&linger, 0, sizeof(linger)); + linger.l_onoff = 1; + linger.l_linger = 0; + if (setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger))) + { soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + } + else if (soap->connect_flags && setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, soap->connect_flags, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "setsockopt failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + if (soap->keep_alive && setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + if (setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + if (setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } +#ifdef TCP_NODELAY + if (!(soap->omode & SOAP_IO_UDP) && setsockopt((SOAP_SOCKET)fd, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } +#endif +#endif + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Opening socket %d to host='%s' port=%d\n", fd, host, port)); +#ifndef WITH_IPV6 + soap->peerlen = sizeof(soap->peer); + memset((void*)&soap->peer, 0, sizeof(soap->peer)); + soap->peer.sin_family = AF_INET; + soap->errmode = 2; + if (soap->proxy_host) + { if (soap->fresolve(soap, soap->proxy_host, &soap->peer.sin_addr)) + { soap_set_sender_error(soap, tcp_error(soap), "get proxy host by name failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + soap->peer.sin_port = htons((short)soap->proxy_port); + } + else + { if (soap->fresolve(soap, host, &soap->peer.sin_addr)) + { soap_set_sender_error(soap, tcp_error(soap), "get host by name failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + soap->peer.sin_port = htons((short)port); + } + soap->errmode = 0; + if ((soap->omode & SOAP_IO_UDP)) + return fd; +#endif +#ifndef WITH_LEAN + if (soap->connect_timeout) +#if defined(WIN32) + { u_long nonblocking = 1; + ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &nonblocking); + } +#elif defined(VXWORKS) + { u_long nonblocking = 1; + ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&nonblocking)); /* modified to use fd */ + } +#else + fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)|O_NONBLOCK); +#endif + else +#if defined(WIN32) + { u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &blocking); + } +#elif defined(VXWORKS) + { u_long blocking = 0; + ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&blocking)); + } +#else + fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)&~O_NONBLOCK); +#endif +#endif + for (;;) + { +#ifdef WITH_IPV6 + if (connect((SOAP_SOCKET)fd, res->ai_addr, res->ai_addrlen)) +#else + if (connect((SOAP_SOCKET)fd, (struct sockaddr*)&soap->peer, sizeof(soap->peer))) +#endif + { +#ifndef WITH_LEAN + if (soap->connect_timeout && (soap_socket_errno(fd) == SOAP_EINPROGRESS || soap_socket_errno(fd) == SOAP_EWOULDBLOCK)) + { struct timeval timeout; + SOAP_SOCKLEN_T k; + fd_set fds; + if (soap->connect_timeout > 0) + { timeout.tv_sec = soap->connect_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->connect_timeout/1000000; + timeout.tv_usec = -soap->connect_timeout%1000000; + } +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + { soap->error = SOAP_FD_EXCEEDED; + return SOAP_INVALID_SOCKET; /* Hint: MUST increase FD_SETSIZE */ + } +#endif + FD_ZERO(&fds); + FD_SET((SOAP_SOCKET)fd, &fds); + for (;;) + { register int r = select((SOAP_SOCKET)(fd + 1), NULL, &fds, NULL, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n")); + soap_set_sender_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + r = soap_socket_errno(fd); + if (r != SOAP_EINTR) + { soap->errnum = r; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); + soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + } + k = (SOAP_SOCKLEN_T)sizeof(soap->errnum); + if (!getsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_ERROR, (char*)&soap->errnum, &k) && !soap->errnum) /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */ + break; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); + if (!soap->errnum) + soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + else +#endif +#ifdef WITH_IPV6 + if (res->ai_next) + { res = res->ai_next; + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + goto again; + } + else +#endif + err = soap_socket_errno(fd); + if (err && err != SOAP_EINTR) + { soap->errnum = err; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); + soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + } + else + break; + } +#ifdef WITH_IPV6 + soap->peerlen = 0; /* IPv6: already connected so use send() */ + freeaddrinfo(ressave); +#endif +#ifndef WITH_LEAN + if (soap->connect_timeout) +#if defined(WIN32) + { u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &blocking); + } +#elif defined(VXWORKS) + { u_long blocking = 0; + ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&blocking)); + } +#else + fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)&~O_NONBLOCK); +#endif +#endif + soap->socket = fd; + soap->imode &= ~SOAP_ENC_SSL; + soap->omode &= ~SOAP_ENC_SSL; + if (!soap_tag_cmp(endpoint, "https:*")) + { +#ifdef WITH_OPENSSL + BIO *bio; + int r; + if (soap->proxy_host) + { unsigned int k = soap->omode; /* make sure we only parse HTTP */ + size_t n = soap->count; /* save the content length */ + char *userid, *passwd; + char endp[sizeof(soap->endpoint)]; + soap->omode &= ~SOAP_ENC; /* mask IO and ENC */ + soap->omode |= SOAP_IO_BUFFER; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connecting to %s proxy server\n", soap->proxy_http_version)); + sprintf(soap->tmpbuf, "CONNECT %s:%d HTTP/%s", host, port, soap->proxy_http_version); + if (soap_begin_send(soap) + || (soap->error = soap->fposthdr(soap, soap->tmpbuf, NULL))) + { soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } +#ifndef WITH_LEAN + if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761) + { sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd); + strcpy(soap->tmpbuf, "Basic "); + soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, strlen(soap->tmpbuf + 262)); + if ((soap->error = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf))) + { soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return soap->error; + } + } +#endif + if ((soap->error = soap->fposthdr(soap, NULL, NULL)) + || soap_flush(soap)) + { soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + soap->omode = k; + k = soap->imode; + soap->imode &= ~SOAP_ENC; /* mask IO and ENC */ + strcpy(endp, soap->endpoint); + userid = soap->userid; /* preserve */ + passwd = soap->passwd; /* preserve */ + if ((soap->error = soap->fparse(soap))) + { soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + strcpy(soap->endpoint, endp); /* restore */ + soap->userid = userid; /* restore */ + soap->passwd = passwd; /* restore */ + soap->imode = k; /* restore */ + soap->count = n; /* restore */ + if (soap_begin_send(soap)) + { soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + } + if (!soap->ctx && (soap->error = soap->fsslauth(soap))) + { soap_set_sender_error(soap, "SSL error", "SSL authentication failed in tcp_connect(): check password, key file, and ca file.", SOAP_SSL_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + soap->ssl = SSL_new(soap->ctx); + if (!soap->ssl) + { soap->fclosesocket(soap, (SOAP_SOCKET)fd); + soap->error = SOAP_SSL_ERROR; + return SOAP_INVALID_SOCKET; + } + if (soap->session) + { if (!strcmp(soap->session_host, host) && soap->session_port == port) + SSL_set_session(soap->ssl, soap->session); + SSL_SESSION_free(soap->session); + soap->session = NULL; + } + soap->imode |= SOAP_ENC_SSL; + soap->omode |= SOAP_ENC_SSL; + bio = BIO_new_socket((SOAP_SOCKET)fd, BIO_NOCLOSE); + SSL_set_bio(soap->ssl, bio, bio); +#ifndef WITH_LEAN + if (soap->connect_timeout) +#if defined(WIN32) + { u_long nonblocking = 1; + ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &nonblocking); + } +#elif defined(VXWORKS) + { u_long nonblocking = 1; + ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&nonblocking)); + } +#else + fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)|O_NONBLOCK); +#endif +#endif + for (;;) + { if ((r = SSL_connect(soap->ssl)) <= 0) + { int err = SSL_get_error(soap->ssl, r); + if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) + { soap_set_sender_error(soap, soap_ssl_error(soap, r), "SSL connect failed in tcp_connect()", SOAP_SSL_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + if (soap->connect_timeout) + { struct timeval timeout; + fd_set fds; + if (soap->connect_timeout > 0) + { timeout.tv_sec = soap->connect_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->connect_timeout/1000000; + timeout.tv_usec = -soap->connect_timeout%1000000; + } +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + { soap->error = SOAP_FD_EXCEEDED; + return SOAP_INVALID_SOCKET; /* Hint: MUST increase FD_SETSIZE */ + } +#endif + FD_ZERO(&fds); + FD_SET((SOAP_SOCKET)fd, &fds); + for (;;) + { int r = select((SOAP_SOCKET)(fd + 1), &fds, NULL, &fds, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n")); + soap_set_sender_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + } + continue; + } + } + break; + } +#ifndef WITH_LEAN + if (soap->connect_timeout) +#ifdef WIN32 + { u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &blocking); + } +#elif defined(VXWORKS) + { u_long blocking = 0; + ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&blocking)); + } +#else + fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)&~O_NONBLOCK); +#endif +#endif + if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION)) + { int err; + // TODO: add callback to verify server + if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK) + { soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL certificate presented by peer cannot be verified in tcp_connect()", SOAP_SSL_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + if (!(soap->ssl_flags & SOAP_SSL_SKIP_HOST_CHECK)) + { X509_NAME *subj; + int ext_count; + int ok = 0; + X509 *peer; + peer = SSL_get_peer_certificate(soap->ssl); + if (!peer) + { soap_set_sender_error(soap, "SSL error", "No SSL certificate was presented by the peer in tcp_connect()", SOAP_SSL_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + ext_count = X509_get_ext_count(peer); + if (ext_count > 0) + { int i; + for (i = 0; i < ext_count; i++) + { X509_EXTENSION *ext = X509_get_ext(peer, i); + const char *ext_str = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext))); + if (ext_str && !strcmp(ext_str, "subjectAltName")) + { X509V3_EXT_METHOD *meth = X509V3_EXT_get(ext); + void *ext_data; + unsigned char *data; + STACK_OF(CONF_VALUE) *val; + int j; + if (!meth) + break; + data = ext->value->data; +#if (OPENSSL_VERSION_NUMBER > 0x00907000L) + if (meth->it) + ext_data = ASN1_item_d2i(NULL, &data, ext->value->length, ASN1_ITEM_ptr(meth->it)); + else + { /* OpenSSL not perfectly portable at this point (?): + Some compilers appear to prefer + meth->d2i(NULL, (const unsigned char**)&data, ... + */ + ext_data = meth->d2i(NULL, &data, ext->value->length); + } +#else + ext_data = meth->d2i(NULL, &data, ext->value->length); +#endif + val = meth->i2v(meth, ext_data, NULL); + for (j = 0; j < sk_CONF_VALUE_num(val); j++) + { CONF_VALUE *nval = sk_CONF_VALUE_value(val, j); + if (nval && !strcmp(nval->name, "DNS") && !strcmp(nval->value, host)) + { ok = 1; + break; + } + } + } + if (ok) + break; + } + } + if (!ok && (subj = X509_get_subject_name(peer))) + { int i = -1; + do + { ASN1_STRING *name; + i = X509_NAME_get_index_by_NID(subj, NID_commonName, i); + if (i == -1) + break; + name = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subj, i)); + if (name && !soap_tag_cmp((const char*)name, host)) + ok = 1; + else + { unsigned char *tmp = NULL; + ASN1_STRING_to_UTF8(&tmp, name); + if (tmp) + { if (!soap_tag_cmp((const char*)tmp, host)) + ok = 1; + OPENSSL_free(tmp); + } + } + } while (!ok); + } + X509_free(peer); + if (!ok) + { soap_set_sender_error(soap, "SSL error", "SSL certificate host name mismatch in tcp_connect()", SOAP_SSL_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + } + } +#else + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + soap->error = SOAP_SSL_ERROR; + return SOAP_INVALID_SOCKET; +#endif + } + return fd; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_bind(struct soap *soap, const char *host, int port, int backlog) +{ +#ifdef WITH_IPV6 + struct addrinfo *addrinfo = NULL; + struct addrinfo hints; + struct addrinfo res; + int err; +#endif +#ifndef WITH_LEAN + int len = SOAP_BUFLEN; + int set = 1; +#endif + if (soap_valid_socket(soap->master)) + { soap->fclosesocket(soap, (SOAP_SOCKET)soap->master); + soap->master = SOAP_INVALID_SOCKET; + } + soap->socket = SOAP_INVALID_SOCKET; + soap->errmode = 1; + if (tcp_init(soap)) + { soap_set_receiver_error(soap, tcp_error(soap), "TCP init failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#ifdef WITH_IPV6 + memset((void*)&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + hints.ai_socktype = SOCK_DGRAM; + else +#endif + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + soap->errmode = 2; + err = getaddrinfo(host, soap_int2s(soap, port), &hints, &addrinfo); + if (addrinfo) + { res = *addrinfo; + soap->peer = *((struct sockaddr_storage*)addrinfo->ai_addr); + soap->peerlen = addrinfo->ai_addrlen; + res.ai_addr = (struct sockaddr*)&soap->peer; + res.ai_addrlen = soap->peerlen; + freeaddrinfo(addrinfo); + } + if (err) + { soap_set_receiver_error(soap, gai_strerror(err), "getaddrinfo failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + soap->master = socket(res.ai_family, res.ai_socktype, res.ai_protocol); +#else +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + soap->master = (int)socket(AF_INET, SOCK_DGRAM, 0); + else +#endif + soap->master = (int)socket(AF_INET, SOCK_STREAM, 0); +#endif + soap->errmode = 0; + if (!soap_valid_socket(soap->master)) + { soap->errnum = soap_socket_errno(soap->master); + soap_set_receiver_error(soap, tcp_error(soap), "socket failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + soap->socket = soap->master; +#endif +#ifdef SOCKET_CLOSE_ON_EXEC +#ifdef WIN32 +#ifndef UNDER_CE + SetHandleInformation((HANDLE)soap->master, HANDLE_FLAG_INHERIT, 0); +#endif +#else + fcntl(soap->master, F_SETFD, 1); +#endif +#endif +#ifndef WITH_LEAN + if (soap->bind_flags && setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, soap->bind_flags, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->master); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->master); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + if (setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->master); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + if (setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->master); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#ifdef TCP_NODELAY + if (!(soap->omode & SOAP_IO_UDP) && setsockopt((SOAP_SOCKET)soap->master, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->master); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#endif +#endif +#ifdef WITH_IPV6 + soap->errmode = 0; + if (bind((SOAP_SOCKET)soap->master, res.ai_addr, res.ai_addrlen)) + { soap->errnum = soap_socket_errno(soap->master); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n")); + soap_closesock(soap); + soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#else + soap->peerlen = sizeof(soap->peer); + memset((void*)&soap->peer, 0, sizeof(soap->peer)); + soap->peer.sin_family = AF_INET; + soap->errmode = 2; + if (host) + { if (soap->fresolve(soap, host, &soap->peer.sin_addr)) + { soap_set_receiver_error(soap, tcp_error(soap), "get host by name failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + } + else + soap->peer.sin_addr.s_addr = htonl(INADDR_ANY); + soap->peer.sin_port = htons((short)port); + soap->errmode = 0; + if (bind((SOAP_SOCKET)soap->master, (struct sockaddr*)&soap->peer, soap->peerlen)) + { soap->errnum = soap_socket_errno(soap->master); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n")); + soap_closesock(soap); + soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#endif + if (!(soap->omode & SOAP_IO_UDP) && listen((SOAP_SOCKET)soap->master, backlog)) + { soap->errnum = soap_socket_errno(soap->master); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n")); + soap_closesock(soap); + soap_set_receiver_error(soap, tcp_error(soap), "listen failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + return soap->master; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_poll(struct soap *soap) +{ +#ifndef WITH_LEAN + struct timeval timeout; + fd_set rfd, sfd, xfd; + int r; + timeout.tv_sec = 0; + timeout.tv_usec = 0; +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + return SOAP_FD_EXCEEDED; /* Hint: MUST increase FD_SETSIZE */ +#endif + FD_ZERO(&rfd); + FD_ZERO(&sfd); + FD_ZERO(&xfd); + if (soap_valid_socket(soap->socket)) + { FD_SET((SOAP_SOCKET)soap->socket, &rfd); + FD_SET((SOAP_SOCKET)soap->socket, &sfd); + FD_SET((SOAP_SOCKET)soap->socket, &xfd); + r = select((SOAP_SOCKET)(soap->socket + 1), &rfd, &sfd, &xfd, &timeout); + if (r > 0 && FD_ISSET((SOAP_SOCKET)soap->socket, &xfd)) + r = -1; + } + else if (soap_valid_socket(soap->master)) + { FD_SET((SOAP_SOCKET)soap->master, &sfd); + r = select((SOAP_SOCKET)(soap->master + 1), NULL, &sfd, NULL, &timeout); + } + else + return SOAP_OK; + if (r > 0) + { +#ifdef WITH_OPENSSL + if (soap->imode & SOAP_ENC_SSL) + { + if (soap_valid_socket(soap->socket) + && FD_ISSET((SOAP_SOCKET)soap->socket, &sfd) + && (!FD_ISSET((SOAP_SOCKET)soap->socket, &rfd) + || SSL_peek(soap->ssl, soap->tmpbuf, 1) > 0)) + return SOAP_OK; + } + else +#endif + if (soap_valid_socket(soap->socket) + && FD_ISSET((SOAP_SOCKET)soap->socket, &sfd) + && (!FD_ISSET((SOAP_SOCKET)soap->socket, &rfd) + || recv((SOAP_SOCKET)soap->socket, soap->tmpbuf, 1, MSG_PEEK) > 0)) + return SOAP_OK; + } + else if (r < 0) + { soap->errnum = soap_socket_errno(soap->master); + if ((soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) && soap_socket_errno(soap->master) != SOAP_EINTR) + { soap_set_receiver_error(soap, tcp_error(soap), "select failed in soap_poll()", SOAP_TCP_ERROR); + return soap->error = SOAP_TCP_ERROR; + } + } + else + soap->errnum = 0; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Polling: other end down on socket=%d select=%d\n", soap->socket, r)); + return SOAP_EOF; +#else + return SOAP_OK; +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_accept(struct soap *soap, int s, struct sockaddr *a, int *n) +{ int fd; + fd = (int)accept((SOAP_SOCKET)s, a, (SOAP_SOCKLEN_T*)n); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */ +#ifdef SOCKET_CLOSE_ON_EXEC +#ifdef WIN32 +#ifndef UNDER_CE + SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0); +#endif +#else + fcntl(fd, F_SETFD, FD_CLOEXEC); +#endif +#endif + return fd; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_accept(struct soap *soap) +{ int n = (int)sizeof(soap->peer); +#ifndef WITH_LEAN + int len = SOAP_BUFLEN; + int set = 1; +#endif + soap->error = SOAP_OK; +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + return soap->socket = soap->master; +#endif + memset((void*)&soap->peer, 0, sizeof(soap->peer)); + soap->socket = SOAP_INVALID_SOCKET; + soap->errmode = 0; + soap->keep_alive = 0; + if (soap_valid_socket(soap->master)) + { register int err; + for (;;) + { +#ifndef WITH_LEAN + if (soap->accept_timeout) + { struct timeval timeout; + fd_set fd; + if (soap->accept_timeout > 0) + { timeout.tv_sec = soap->accept_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->accept_timeout/1000000; + timeout.tv_usec = -soap->accept_timeout%1000000; + } +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + { soap->error = SOAP_FD_EXCEEDED; + return SOAP_INVALID_SOCKET; /* Hint: MUST increase FD_SETSIZE */ + } +#endif + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->master, &fd); + for (;;) + { register int r = select((SOAP_SOCKET)(soap->master + 1), &fd, &fd, NULL, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + soap_set_receiver_error(soap, "Timeout", "accept failed in soap_accept()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + r = soap_socket_errno(soap->master); + if (r != SOAP_EINTR) + { soap->errnum = r; + soap_closesock(soap); + soap_set_sender_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + } +#if defined(WIN32) + { u_long nonblocking = 1; + ioctlsocket((SOAP_SOCKET)soap->master, FIONBIO, &nonblocking); + } +#elif defined(VXWORKS) + { u_long nonblocking = 1; + ioctl((SOAP_SOCKET)soap->master, FIONBIO, (int)(&nonblocking)); + } +#else + fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL)|O_NONBLOCK); +#endif + } + else +#if defined(WIN32) + { u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)soap->master, FIONBIO, &blocking); + } +#elif defined(VXWORKS) + { u_long blocking = 0; + ioctl((SOAP_SOCKET)soap->master, FIONBIO, (int)(&blocking)); + } +#else + fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL)&~O_NONBLOCK); +#endif +#endif + soap->socket = soap->faccept(soap, soap->master, (struct sockaddr*)&soap->peer, &n); + soap->peerlen = (size_t)n; + if (soap_valid_socket(soap->socket)) + { +#ifdef WITH_IPV6 +/* Use soap->host to store the numeric form of the remote host */ + getnameinfo((struct sockaddr*)&soap->peer, n, soap->host, sizeof(soap->host), NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket %d from %s\n", soap->socket, soap->host)); + soap->ip = 0; /* info stored in soap->peer and soap->host */ + soap->port = 0; /* info stored in soap->peer and soap->host */ +#else + soap->ip = ntohl(soap->peer.sin_addr.s_addr); + soap->port = (int)ntohs(soap->peer.sin_port); /* does not return port number on some systems */ + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket %d at port %d from IP %d.%d.%d.%d\n", soap->socket, soap->port, (int)(soap->ip>>24)&0xFF, (int)(soap->ip>>16)&0xFF, (int)(soap->ip>>8)&0xFF, (int)soap->ip&0xFF)); +#endif +#ifndef WITH_LEAN + if (soap->accept_flags == SO_LINGER) + { struct linger linger; + memset((void*)&linger, 0, sizeof(linger)); + linger.l_onoff = 1; + linger.l_linger = 0; + if (setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger))) + { soap->errnum = soap_socket_errno(soap->socket); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } + } + else if (soap->accept_flags && setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, soap->accept_flags, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->socket); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } + if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->socket); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } + if (setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->socket); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } + if (setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->socket); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } +#ifdef TCP_NODELAY + if (!(soap->omode & SOAP_IO_UDP) && setsockopt((SOAP_SOCKET)soap->socket, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->socket); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } +#endif +#endif + if (soap->accept_timeout) + { +#if defined(WIN32) + u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)soap->master, FIONBIO, &blocking); + ioctlsocket((SOAP_SOCKET)soap->socket, FIONBIO, &blocking); +#elif defined(VXWORKS) + u_long blocking = 0; + ioctl((SOAP_SOCKET)soap->master, FIONBIO, (int)(&blocking)); + ioctl((SOAP_SOCKET)soap->socket, FIONBIO, (int)(&blocking)); +#elif defined(PALM) + fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL,0)&~O_NONBLOCK); + fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL,0)&~O_NONBLOCK); +#elif defined(SYMBIAN) + long blocking = 0; + ioctl((SOAP_SOCKET)soap->master, 0/*FIONBIO*/, &blocking); +#else + fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL)&~O_NONBLOCK); + fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL)&~O_NONBLOCK); +#endif + } + soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0); + return soap->socket; + } + err = soap_socket_errno(soap->socket); + if (err != 0 && err != SOAP_EINTR && err != SOAP_EAGAIN) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept failed from %s\n", soap->host)); + soap->errnum = err; + soap_set_receiver_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } + } + } + else + { soap->errnum = 0; + soap_set_receiver_error(soap, tcp_error(soap), "no master socket in soap_accept()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_disconnect(struct soap *soap) +{ +#ifdef WITH_OPENSSL + if (soap->ssl) + { int r, s = 0; + if (soap->session) + SSL_SESSION_free(soap->session); + if (*soap->host) + { soap->session = SSL_get1_session(soap->ssl); + if (soap->session) + { strcpy(soap->session_host, soap->host); + soap->session_port = soap->port; + } + } + r = SSL_shutdown(soap->ssl); + if (r != 1) + { s = ERR_get_error(); + if (s) + { if (soap_valid_socket(soap->socket)) + { soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 1); + soap->socket = SOAP_INVALID_SOCKET; + } + r = SSL_shutdown(soap->ssl); + } + } + DBGLOG(TEST, if (s) SOAP_MESSAGE(fdebug, "Shutdown failed: %d\n", SSL_get_error(soap->ssl, r))); + SSL_free(soap->ssl); + soap->ssl = NULL; + if (s) + return SOAP_SSL_ERROR; + ERR_remove_state(0); + } +#endif + if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP)) + { soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 2); + soap->fclosesocket(soap, (SOAP_SOCKET)soap->socket); + soap->socket = SOAP_INVALID_SOCKET; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_closesocket(struct soap *soap, SOAP_SOCKET fd) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Close socket %d\n", (int)fd)); + return soap_closesocket(fd); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_shutdownsocket(struct soap *soap, SOAP_SOCKET fd, int how) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown socket %d how=%d\n", (int)fd, how)); + return shutdown(fd, how); +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_closesock(struct soap *soap) +{ register int status = soap->error; + if (status == SOAP_EOF || status == SOAP_TCP_ERROR || status == SOAP_SSL_ERROR || !soap->keep_alive) + { if (soap->fclose && (soap->error = soap->fclose(soap))) + return soap->error; + soap->keep_alive = 0; + } +#ifdef WITH_ZLIB + if (soap->zlib_state == SOAP_ZLIB_DEFLATE) + deflateEnd(&soap->d_stream); + else if (soap->zlib_state == SOAP_ZLIB_INFLATE) + inflateEnd(&soap->d_stream); + soap->zlib_state = SOAP_ZLIB_NONE; +#endif + return soap->error = status; +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_hash(register const char *s) +{ register size_t h = 0; + while (*s) + h = 65599*h + *s++; + return h % SOAP_IDHASH; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static void +soap_init_pht(struct soap *soap) +{ register int i; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing pointer hashtable\n")); + soap->pblk = NULL; + soap->pidx = 0; + for (i = 0; i < (int)SOAP_PTRHASH; i++) + soap->pht[i] = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_new1(soap_mode mode) +{ return soap_new2(mode, mode); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_new() +{ return soap_new2(SOAP_IO_DEFAULT, SOAP_IO_DEFAULT); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_new2(soap_mode imode, soap_mode omode) +{ struct soap *soap = (struct soap*)malloc(sizeof(struct soap)); + if (soap) + soap_init2(soap, imode, omode); + return soap; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_free(struct soap *soap) +{ soap_done(soap); + free(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_del(struct soap *soap) +{ free(soap); +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static void +soap_free_pht(struct soap *soap) +{ register struct soap_pblk *pb, *next; + register int i; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free pointer hashtable\n")); + for (pb = soap->pblk; pb; pb = next) + { next = pb->next; + SOAP_FREE(soap, pb); + } + soap->pblk = NULL; + soap->pidx = 0; + for (i = 0; i < (int)SOAP_PTRHASH; i++) + soap->pht[i] = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_embed(struct soap *soap, const void *p, const struct soap_array *a, int n, const char *tag, int type) +{ register int i; + struct soap_plist *pp; + if (soap->version != 1) + soap->encoding = 1; + if (a) + i = soap_array_pointer_lookup(soap, p, a, n, type, &pp); + else + i = soap_pointer_lookup(soap, p, type, &pp); + if (i) + { if (soap_is_embedded(soap, pp) + || soap_is_single(soap, pp)) + return 0; + soap_set_embedded(soap, pp); + } + return i; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_pointer_lookup(struct soap *soap, const void *p, int type, struct soap_plist **ppp) +{ register struct soap_plist *pp; + *ppp = NULL; + if (p) + { for (pp = soap->pht[soap_hash_ptr(p)]; pp; pp = pp->next) + { if (pp->ptr == p && pp->type == type) + { *ppp = pp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d id=%d\n", p, type, pp->id)); + return pp->id; + } + } + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d: not found\n", p, type)); + return 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_pointer_enter(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp) +{ register size_t h; + register struct soap_plist *pp; + if (!soap->pblk || soap->pidx >= SOAP_PTRBLK) + { register struct soap_pblk *pb = (struct soap_pblk*)SOAP_MALLOC(soap, sizeof(struct soap_pblk)); + if (!pb) + { soap->error = SOAP_EOM; + return 0; + } + pb->next = soap->pblk; + soap->pblk = pb; + soap->pidx = 0; + } + *ppp = pp = &soap->pblk->plist[soap->pidx++]; + if (a) + h = soap_hash_ptr(a->__ptr); + else + h = soap_hash_ptr(p); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pointer enter location=%p array=%p size=%d dim=%d type=%d id=%d\n", p, a?a->__ptr:NULL, a?a->__size:0, n, type, soap->idnum+1)); + pp->next = soap->pht[h]; + pp->type = type; + pp->mark1 = 0; + pp->mark2 = 0; + pp->ptr = p; + pp->array = a; + soap->pht[h] = pp; + pp->id = ++soap->idnum; + return pp->id; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_array_pointer_lookup(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp) +{ register struct soap_plist *pp; + *ppp = NULL; + if (!p || !a->__ptr) + return 0; + for (pp = soap->pht[soap_hash_ptr(a->__ptr)]; pp; pp = pp->next) + { if (pp->type == type && pp->array && pp->array->__ptr == a->__ptr) + { register int i; + for (i = 0; i < n; i++) + if (((const int*)&pp->array->__size)[i] != ((const int*)&a->__size)[i]) + break; + if (i == n) + { *ppp = pp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d id=%d\n", a->__ptr, type, pp->id)); + return pp->id; + } + } + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d: not found\n", a->__ptr, type)); + return 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_begin_count(struct soap *soap) +{ +#ifndef WITH_LEANER + if ((soap->mode & SOAP_ENC_DIME) || (soap->omode & SOAP_ENC_DIME)) + soap->mode = soap->omode | SOAP_IO_LENGTH | SOAP_ENC_DIME; + else +#endif + { soap->mode = soap->omode; + if ((soap->mode & SOAP_IO) == SOAP_IO_STORE + || (((soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_ENC_XML)) +#ifndef WITH_LEANER + && !soap->fpreparesend +#endif + )) + soap->mode &= ~SOAP_IO_LENGTH; + else + soap->mode |= SOAP_IO_LENGTH; + } +#ifdef WITH_ZLIB + if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH) + { if (!(soap->mode & SOAP_ENC_DIME)) + soap->mode &= ~SOAP_IO_LENGTH; + if (soap->mode & SOAP_ENC_XML) + soap->mode |= SOAP_IO_BUFFER; + else + soap->mode |= SOAP_IO_STORE; + } +#endif + if (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH)) + soap->mode |= SOAP_XML_TREE; +#ifndef WITH_LEANER + if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME)) + soap->mode |= SOAP_ENC_MIME; + else + soap->mode &= ~SOAP_ENC_MTOM; + if (soap->mode & SOAP_ENC_MIME) + soap_select_mime_boundary(soap); + soap->dime.list = soap->dime.last; /* keep track of last DIME attachment */ +#endif + soap->count = 0; + soap->ns = 0; + soap->null = 0; + soap->position = 0; + soap->mustUnderstand = 0; + soap->encoding = 0; + soap->part = SOAP_BEGIN; + soap->idnum = 0; + soap_clr_attr(soap); + soap_set_local_namespaces(soap); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin count phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count)); +#ifndef WITH_LEANER + soap->dime.count = 0; /* count # of attachments */ + soap->dime.size = 0; /* accumulate total size of attachments */ + if (soap->fprepareinit && (soap->mode & SOAP_IO) != SOAP_IO_STORE) + return soap->error = soap->fprepareinit(soap); +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_end_count(struct soap *soap) +{ +#ifndef WITH_LEANER + if (soap->fpreparefinal) + return soap->error = soap->fpreparefinal(soap); +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of count phase\n")); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_begin_send(struct soap *soap) +{ soap->error = SOAP_OK; + soap->mode = soap->omode | (soap->mode & (SOAP_IO_LENGTH | SOAP_ENC_DIME)); +#ifdef WITH_ZLIB + if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH) + { if (soap->mode & SOAP_ENC_XML) + soap->mode |= SOAP_IO_BUFFER; + else + soap->mode |= SOAP_IO_STORE; + } +#endif +#ifdef WITH_UDP + if ((soap->mode & SOAP_IO_UDP)) + { soap->mode |= SOAP_ENC_XML; + if (soap->count > SOAP_BUFLEN) + return soap->error = SOAP_UDP_ERROR; + } +#endif + if ((soap->mode & SOAP_IO) == SOAP_IO_FLUSH && soap_valid_socket(soap->socket)) + { if (soap->count || (soap->mode & SOAP_IO_LENGTH) || (soap->mode & SOAP_ENC_XML)) + soap->mode |= SOAP_IO_BUFFER; + else + soap->mode |= SOAP_IO_STORE; + } + soap->mode &= ~SOAP_IO_LENGTH; + if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) + soap_new_block(soap); + if (!(soap->mode & SOAP_IO_KEEPALIVE)) + soap->keep_alive = 0; + if (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH)) + soap->mode |= SOAP_XML_TREE; +#ifndef WITH_LEANER + if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME)) + { soap->mode |= SOAP_ENC_MIME; + soap->mode &= ~SOAP_ENC_DIME; + } + else + soap->mode &= ~SOAP_ENC_MTOM; + if (soap->mode & SOAP_ENC_MIME) + soap_select_mime_boundary(soap); +#ifdef WIN32 +#ifndef UNDER_CE +#ifndef WITH_FASTCGI + if (!soap_valid_socket(soap->socket)) /* Set win32 stdout or soap->sendfd to BINARY, e.g. to support DIME */ +#ifdef __BORLANDC__ + setmode((SOAP_SOCKET)soap->sendfd, O_BINARY); +#else + _setmode((SOAP_SOCKET)soap->sendfd, _O_BINARY); +#endif +#endif +#endif +#endif +#endif + if (soap->mode & SOAP_IO) + { soap->bufidx = 0; + soap->buflen = 0; + } + soap->chunksize = 0; + soap->ns = 0; + soap->null = 0; + soap->position = 0; + soap->mustUnderstand = 0; + soap->encoding = 0; + soap->idnum = 0; + soap->level = 0; + soap_clr_attr(soap); + soap_set_local_namespaces(soap); +#ifdef WITH_ZLIB + soap->z_ratio_out = 1.0; + if ((soap->mode & SOAP_ENC_ZLIB) && soap->zlib_state != SOAP_ZLIB_DEFLATE) + { +#ifdef WITH_GZIP + memcpy(soap->z_buf, "\37\213\10\0\0\0\0\0\0\377", 10); + soap->d_stream.next_out = (Byte*)soap->z_buf + 10; + soap->d_stream.avail_out = SOAP_BUFLEN - 10; + soap->z_crc = crc32(0L, NULL, 0); + if (deflateInit2(&soap->d_stream, soap->z_level, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY) != Z_OK) +#else + soap->d_stream.next_out = (Byte*)soap->z_buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + if (deflateInit(&soap->d_stream, soap->z_level) != Z_OK) +#endif + return soap->error = SOAP_ZLIB_ERROR; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflate initialized\n")); + soap->zlib_state = SOAP_ZLIB_DEFLATE; + } +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin send phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count)); + soap->part = SOAP_BEGIN; +#ifndef WITH_LEANER + if (soap->fprepareinit && (soap->mode & SOAP_IO) == SOAP_IO_STORE) + soap->fprepareinit(soap); +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_embedded(struct soap *soap, const void *p, int t) +{ struct soap_plist *pp; + if (soap_pointer_lookup(soap, p, t, &pp)) + { pp->mark1 = 1; + pp->mark2 = 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded %p type=%d mark set to 1\n", p, t)); + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_reference(struct soap *soap, const void *p, int t) +{ struct soap_plist *pp; + if (!p || (soap->mode & SOAP_XML_TREE)) + return 1; + if (soap_pointer_lookup(soap, p, t, &pp)) + { if (pp->mark1 == 0) + { pp->mark1 = 2; + pp->mark2 = 2; + } + } + else if (soap_pointer_enter(soap, p, NULL, 0, t, &pp)) + { pp->mark1 = 0; + pp->mark2 = 0; + } + else + return 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reference %p type=%d (%d %d)\n", p, t, (int)pp->mark1, (int)pp->mark2)); + return pp->mark1; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_array_reference(struct soap *soap, const void *p, const struct soap_array *a, int n, int t) +{ register int i; + struct soap_plist *pp; + if (!p || !a->__ptr) + return 1; + i = soap_array_pointer_lookup(soap, p, a, n, t, &pp); + if (i) + { if (pp->mark1 == 0) + { pp->mark1 = 2; + pp->mark2 = 2; + } + } + else if (!soap_pointer_enter(soap, p, a, n, t, &pp)) + return 1; + else + { pp->mark1 = 0; + pp->mark2 = 0; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array reference %p ptr=%p dim=%d type=%d (%d %d)\n", p, a->__ptr, n, t, (int)pp->mark1, (int)pp->mark2)); + return pp->mark1; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_embedded_id(struct soap *soap, int id, const void *p, int t) +{ struct soap_plist *pp; + if (soap->mode & SOAP_XML_TREE) + return id; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id %p type=%d id=%d\n", p, t, id)); + if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER) + { if (id < 0) + { id = soap_pointer_lookup(soap, p, t, &pp); + if (id) + { if (soap->mode & SOAP_IO_LENGTH) + pp->mark1 = 2; + else + pp->mark2 = 2; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id multiref id=%d %p type=%d = (%d %d)\n", id, p, t, (int)pp->mark1, (int)pp->mark2)); + } + return -1; + } + return id; + } + if (id < 0) + id = soap_pointer_lookup(soap, p, t, &pp); + else if (id && !soap_pointer_lookup(soap, p, t, &pp)) + return 0; + if (id && pp) + { if (soap->mode & SOAP_IO_LENGTH) + pp->mark1 = 1; + else + pp->mark2 = 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id embedded ref id=%d %p type=%d = (%d %d)\n", id, p, t, (int)pp->mark1, (int)pp->mark2)); + } + return id; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_is_embedded(struct soap *soap, struct soap_plist *pp) +{ if (!pp) + return 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Is embedded? %d %d\n", (int)pp->mark1, (int)pp->mark2)); + if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER) + { if (soap->mode & SOAP_IO_LENGTH) + return pp->mark1 != 0; + return pp->mark2 != 0; + } + if (soap->mode & SOAP_IO_LENGTH) + return pp->mark1 == 1; + return pp->mark2 == 1; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_is_single(struct soap *soap, struct soap_plist *pp) +{ if (soap->part == SOAP_IN_HEADER) + return 1; + if (!pp) + return 0; + if (soap->mode & SOAP_IO_LENGTH) + return pp->mark1 == 0; + return pp->mark2 == 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_embedded(struct soap *soap, struct soap_plist *pp) +{ if (!pp) + return; + if (soap->mode & SOAP_IO_LENGTH) + pp->mark1 = 1; + else + pp->mark2 = 1; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_attachment(struct soap *soap, const char *tag, int id, const void *p, const struct soap_array *a, const char *aid, const char *atype, const char *aoptions, int n, const char *type, int t) +{ struct soap_plist *pp; + int i; + if (!p || !a->__ptr || (!aid && !atype)) + return soap_element_id(soap, tag, id, p, a, n, type, t); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attachment tag='%s' id='%s' (%d) type='%s'\n", tag, aid?aid:"", id, atype?atype:"")); + i = soap_array_pointer_lookup(soap, p, a, n, t, &pp); + if (!i) + { i = soap_pointer_enter(soap, p, a, n, t, &pp); + if (!i) + { soap->error = SOAP_EOM; + return -1; + } + } + if (id <= 0) + id = i; + if (!aid) + { sprintf(soap->tmpbuf, soap->dime_id_format, id); + aid = soap_strdup(soap, soap->tmpbuf); + } + /* Add MTOM xop:Include element when necessary */ + /* TODO: this code to be obsoleted with new import/xop.h conventions */ + if ((soap->mode & SOAP_ENC_MTOM) && strcmp(tag, "xop:Include")) + { if (soap_element_begin_out(soap, tag, 0, type) + || soap_element_href(soap, "xop:Include", 0, "href", aid) + || soap_element_end_out(soap, tag)) + return soap->error; + } + else if (soap_element_href(soap, tag, 0, "href", aid)) + return soap->error; + if (soap->mode & SOAP_IO_LENGTH) + { if (pp->mark1 != 3) + { struct soap_multipart *content; + if (soap->mode & SOAP_ENC_MTOM) + content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, (char*)a->__ptr, a->__size); + else + content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, (char*)a->__ptr, a->__size); + if (!content) + { soap->error = SOAP_EOM; + return -1; + } + if (!strncmp(aid, "cid:", 4)) /* RFC 2111 */ + { if (soap->mode & SOAP_ENC_MTOM) + { char *s = (char*)soap_malloc(soap, strlen(aid) - 1); + if (s) + { *s = '<'; + strcpy(s + 1, aid + 4); + strcat(s, ">"); + content->id = s; + } + } + else + content->id = aid + 4; + } + else + content->id = aid; + content->type = atype; + content->options = aoptions; + content->encoding = SOAP_MIME_BINARY; + pp->mark1 = 3; + } + } + else + pp->mark2 = 3; + return -1; +} +#endif +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static void +soap_init_iht(struct soap *soap) +{ register int i; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing ID hashtable\n")); + for (i = 0; i < SOAP_IDHASH; i++) + soap->iht[i] = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static void +soap_free_iht(struct soap *soap) +{ register int i; + register struct soap_ilist *ip, *p; + register struct soap_flist *fp, *fq; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free ID hashtable\n")); + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = p) + { for (fp = ip->flist; fp; fp = fq) + { fq = fp->next; + SOAP_FREE(soap, fp); + } + p = ip->next; + SOAP_FREE(soap, ip); + } + soap->iht[i] = NULL; + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +struct soap_ilist * +SOAP_FMAC2 +soap_lookup(struct soap *soap, const char *id) +{ register struct soap_ilist *ip; + for (ip = soap->iht[soap_hash(id)]; ip; ip = ip->next) + if (!strcmp(ip->id, id)) + return ip; + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +struct soap_ilist * +SOAP_FMAC2 +soap_enter(struct soap *soap, const char *id) +{ register size_t h; + register struct soap_ilist *ip; + ip = (struct soap_ilist*)SOAP_MALLOC(soap, sizeof(struct soap_ilist) + strlen(id)); + if (ip) + { h = soap_hash(id); + strcpy(ip->id, id); + ip->next = soap->iht[h]; + soap->iht[h] = ip; + return ip; + } + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_malloc(struct soap *soap, size_t n) +{ register char *p; + if (!n) + return (void*)SOAP_NON_NULL; + if (!soap) + return SOAP_MALLOC(soap, n); + if (soap->fmalloc) + p = (char*)soap->fmalloc(soap, n); + else + { n += sizeof(short); + n += (-(long)n) & (sizeof(void*)-1); /* align at 4-, 8- or 16-byte boundary */ + if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(void*) + sizeof(size_t)))) + { soap->error = SOAP_EOM; + return NULL; + } + /* set the canary to detect corruption */ + *(short*)(p + n - sizeof(short)) = (short)SOAP_CANARY; + /* keep chain of alloced cells for destruction */ + *(void**)(p + n) = soap->alist; + *(size_t*)(p + n + sizeof(void*)) = n; + soap->alist = p + n; + } + soap->alloced = 1; + return p; +} +#endif + +/******************************************************************************/ +#ifdef SOAP_MEM_DEBUG +static void +soap_init_mht(struct soap *soap) +{ register int i; + for (i = 0; i < (int)SOAP_PTRHASH; i++) + soap->mht[i] = NULL; +} +#endif + +/******************************************************************************/ +#ifdef SOAP_MEM_DEBUG +static void +soap_free_mht(struct soap *soap) +{ register int i; + register struct soap_mlist *mp, *mq; + for (i = 0; i < (int)SOAP_PTRHASH; i++) + { for (mp = soap->mht[i]; mp; mp = mq) + { mq = mp->next; + if (mp->live) + fprintf(stderr, "%s(%d): malloc() = %p not freed (memory leak or forgot to call soap_end()?)\n", mp->file, mp->line, mp->ptr); + free(mp); + } + soap->mht[i] = NULL; + } +} +#endif + +/******************************************************************************/ +#ifdef SOAP_MEM_DEBUG +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_track_malloc(struct soap *soap, const char *file, int line, size_t size) +{ register void *p = malloc(size); + if (soap) + { register size_t h = soap_hash_ptr(p); + register struct soap_mlist *mp = (struct soap_mlist*)malloc(sizeof(struct soap_mlist)); + if (soap->fdebug[SOAP_INDEX_TEST]) + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): malloc(%lu) = %p\n", file, line, (unsigned long)size, p)); + mp->next = soap->mht[h]; + mp->ptr = p; + mp->file = file; + mp->line = line; + mp->live = 1; + soap->mht[h] = mp; + } + return p; +} +#endif + +/******************************************************************************/ +#ifdef SOAP_MEM_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_track_free(struct soap *soap, const char *file, int line, void *p) +{ register size_t h = soap_hash_ptr(p); + register struct soap_mlist *mp; + for (mp = soap->mht[h]; mp; mp = mp->next) + if (mp->ptr == p) + break; + if (mp) + { if (mp->live) + { free(p); + if (soap->fdebug[SOAP_INDEX_TEST]) + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): free(%p)\n", file, line, p)); + mp->live = 0; + } + else + fprintf(stderr, "%s(%d): free(%p) double free of pointer malloced at %s(%d)\n", file, line, p, mp->file, mp->line); + } + else + fprintf(stderr, "%s(%d): free(%p) pointer not malloced\n", file, line, p); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_MEM_DEBUG +static void +soap_track_unlink(struct soap *soap, const void *p) +{ register size_t h = soap_hash_ptr(p); + register struct soap_mlist *mp; + for (mp = soap->mht[h]; mp; mp = mp->next) + if (mp->ptr == p) + break; + if (mp) + mp->live = 0; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_dealloc(struct soap *soap, void *p) +{ if (soap_check_state(soap)) + return; + if (p) + { register char **q; + for (q = (char**)&soap->alist; *q; q = *(char***)q) + { + if (*(short*)(char*)(*q - sizeof(short)) != (short)SOAP_CANARY) + { fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n"); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n")); + DBGHEX(TEST, *q - 200, 200); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n")); + soap->error = SOAP_MOE; + return; + } + if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*)))) + { *q = **(char***)q; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Freed data at %p\n", p)); + SOAP_FREE(soap, p); + return; + } + } + soap_delete(soap, p); + } + else + { register char *q; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free all soap_malloc() data\n")); + while (soap->alist) + { q = (char*)soap->alist; + if (*(short*)(char*)(q - sizeof(short)) != (short)SOAP_CANARY) + { fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n"); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n")); + DBGHEX(TEST, q - 200, 200); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n")); + soap->error = SOAP_MOE; + return; + } + soap->alist = *(void**)q; + q -= *(size_t*)(q + sizeof(void*)); + SOAP_FREE(soap, q); + } + } + /* we must assume these were deallocated: */ + soap->action = NULL; + soap->fault = NULL; + soap->header = NULL; + soap->userid = NULL; + soap->passwd = NULL; + soap->authrealm = NULL; +#ifndef WITH_LEANER + soap_clr_mime(soap); +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_delete(struct soap *soap, void *p) +{ register struct soap_clist **cp; + if (soap_check_state(soap)) + return; + cp = &soap->clist; + if (p) + { while (*cp) + { if (p == (*cp)->ptr) + { register struct soap_clist *q = *cp; + *cp = q->next; + q->fdelete(q); + SOAP_FREE(soap, q); + return; + } + cp = &(*cp)->next; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: address not in list\n", p)); + } + else + { while (*cp) + { register struct soap_clist *q = *cp; + *cp = q->next; + q->fdelete(q); + SOAP_FREE(soap, q); + } + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +struct soap_clist * +SOAP_FMAC2 +soap_link(struct soap *soap, void *p, int t, int n, void (*fdelete)(struct soap_clist*)) +{ register struct soap_clist *cp; + if ((cp = (struct soap_clist*)SOAP_MALLOC(soap, sizeof(struct soap_clist)))) + { cp->next = soap->clist; + cp->type = t; + cp->size = n; + cp->ptr = p; + cp->fdelete = fdelete; + soap->clist = cp; + } + return cp; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_unlink(struct soap *soap, const void *p) +{ register char **q; + register struct soap_clist **cp; + if (!soap || !p) + return; + for (q = (char**)&soap->alist; *q; q = *(char***)q) + { if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*)))) + { *q = **(char***)q; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked data %p\n", p)); +#ifdef SOAP_DEBUG + soap_track_unlink(soap, p); +#endif + return; + } + } + for (cp = &soap->clist; *cp; cp = &(*cp)->next) + { if (p == (*cp)->ptr) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked class instance %p\n", p)); + q = (char**)*cp; + *cp = (*cp)->next; + SOAP_FREE(soap, q); + return; + } + } +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_lookup_type(struct soap *soap, const char *id) +{ register struct soap_ilist *ip; + if (id && *id) + { ip = soap_lookup(soap, id); + if (ip) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup id='%s' type=%d\n", id, ip->type)); + return ip->type; + } + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "lookup type id='%s' NOT FOUND! Need to get it from xsi:type\n", id)); + return 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_id_lookup(struct soap *soap, const char *id, void **p, int t, size_t n, unsigned int k) +{ struct soap_ilist *ip; + void **q; + if (!p || !id || !*id) + return p; + ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */ + if (!ip) + { ip = soap_enter(soap, id); /* new hash table entry for string id */ + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding first href='%s' type=%d %p (%u bytes)\n", id, t, p, (unsigned int)n)); + ip->type = t; + ip->size = n; + ip->link = p; + ip->copy = NULL; + ip->flist = NULL; + ip->ptr = NULL; + ip->level = k; + *p = NULL; + } + else if (ip->ptr) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolved href='%s' type=%d location=%p (%u bytes)\n", id, t, ip->ptr, (unsigned int)n)); + if (ip->type != t) + { strcpy(soap->id, id); + soap->error = SOAP_HREF; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility: id type=%d href type=%d\n", ip->type, t)); + return NULL; + } + while (ip->level < k) + { q = (void**)soap_malloc(soap, sizeof(void*)); + if (!q) + return NULL; + *p = (void*)q; + p = q; + k--; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); + } + *p = ip->ptr; + } + else if (ip->level > k) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving level %u pointers to href='%s'\n", ip->level, id)); + while (ip->level > k) + { void *s, **r = &ip->link; + q = (void**)ip->link; + while (q) + { *r = (void*)soap_malloc(soap, sizeof(void*)); + s = *q; + *q = *r; + r = (void**)*r; + q = (void**)s; + } + *r = NULL; + ip->size = n; + ip->copy = NULL; + ip->level = ip->level - 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); + } + q = (void**)ip->link; + ip->link = p; + *p = (void*)q; + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarded href='%s' type=%d location=%p (%u bytes)\n", id, t, p, (unsigned int)n)); + while (ip->level < k) + { q = (void**)soap_malloc(soap, sizeof(void*)); + *p = q; + p = q; + k--; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); + } + q = (void**)ip->link; + ip->link = p; + *p = (void*)q; + } + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_id_forward(struct soap *soap, const char *href, void *p, size_t len, int st, int tt, size_t n, unsigned int k, void (*fcopy)(struct soap*, int, int, void*, size_t, const void*, size_t)) +{ struct soap_ilist *ip; + if (!p || !href || !*href) + return p; + ip = soap_lookup(soap, href); /* lookup pointer to hash table entry for string id */ + if (!ip) + { ip = soap_enter(soap, href); /* new hash table entry for string id */ + ip->type = st; + ip->size = n; + ip->link = NULL; + ip->copy = NULL; + ip->ptr = NULL; + ip->level = 0; + ip->flist = NULL; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "New entry href='%s' type=%d size=%lu level=%d location=%p\n", href, st, (unsigned long)n, k, p)); + } + else if (ip->type != st || (ip->level == k && ip->size != n)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n", href, ip->type, (unsigned long)ip->size, k, st, (unsigned long)n)); + strcpy(soap->id, href); + soap->error = SOAP_HREF; + return NULL; + } + if (fcopy || n < sizeof(void*) || *href != '#') + { register struct soap_flist *fp = (struct soap_flist*)SOAP_MALLOC(soap, sizeof(struct soap_flist)); + if (!fp) + { soap->error = SOAP_EOM; + return NULL; + } + fp->next = ip->flist; + fp->type = tt; + fp->ptr = p; + fp->level = k; + fp->len = len; + if (fcopy) + fp->fcopy = fcopy; + else + fp->fcopy = soap_fcopy; + ip->flist = fp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding type=%d (target type=%d) size=%lu location=%p level=%u len=%lu href='%s'\n", st, tt, (unsigned long)n, p, k, (unsigned long)len, href)); + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding copying address %p for type=%d href='%s'\n", p, st, href)); + *(void**)p = ip->copy; + ip->copy = p; + } + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_id_enter(struct soap *soap, const char *id, void *p, int t, size_t n, unsigned int k, const char *type, const char *arrayType, void *(*finstantiate)(struct soap*, int, const char*, const char*, size_t*)) +{ +#ifndef WITH_NOIDREF + struct soap_ilist *ip; +#endif + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Enter id='%s' type=%d loc=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k)); + soap->alloced = 0; + if (!p) + { if (finstantiate) + p = finstantiate(soap, t, type, arrayType, &n); + else + p = soap_malloc(soap, n); + if (p) + soap->alloced = 1; + } +#ifndef WITH_NOIDREF + if (!id || !*id) +#endif + return p; +#ifndef WITH_NOIDREF + ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */ + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Lookup entry id='%s for location=%p'\n", id, p)); + if (!ip) + { ip = soap_enter(soap, id); /* new hash table entry for string id */ + ip->type = t; + ip->link = NULL; + ip->copy = NULL; + ip->flist = NULL; + ip->size = n; + ip->ptr = p; + ip->level = k; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "New entry id='%s' type=%d size=%lu level=%u location=%p\n", id, t, (unsigned long)n, k, p)); + } + else if ((ip->type != t || (ip->level == k && ip->size != n)) && (ip->copy || ip->flist)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n", id, ip->type, (unsigned long)ip->size, k, t, (unsigned long)n)); + strcpy(soap->id, id); + soap->error = SOAP_HREF; + return NULL; + } + else if (ip->ptr) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Multiply defined id='%s'\n", id)); + strcpy(soap->id, id); + soap->error = SOAP_DUPLICATE_ID; + return NULL; + } + else + { ip->size = n; + ip->ptr = p; + ip->level = k; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update entry id='%s' type=%d location=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k)); + } + return ip->ptr; +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_fcopy(struct soap *soap, int st, int tt, void *p, size_t len, const void *q, size_t n) +{ DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Copying data type=%d (target type=%d) %p -> %p (%lu bytes)\n", st, tt, q, p, (unsigned long)n)); + memcpy(p, q, n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_end_send(struct soap *soap) +{ +#ifndef WITH_LEANER + if (soap->dime.list) + { /* SOAP body referenced attachments must appear first */ + soap->dime.last->next = soap->dime.first; + soap->dime.first = soap->dime.list->next; + soap->dime.list->next = NULL; + soap->dime.last = soap->dime.list; + } + if (soap_putdime(soap) || soap_putmime(soap)) + return soap->error; + soap->mime.list = NULL; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->dime.list = NULL; + soap->dime.first = NULL; + soap->dime.last = NULL; +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End send\n")); + if (soap->mode & SOAP_IO) /* need to flush the remaining data in buffer */ + { if (soap_flush(soap)) +#ifdef WITH_ZLIB + { if (soap->mode & SOAP_ENC_ZLIB && soap->zlib_state == SOAP_ZLIB_DEFLATE) + { soap->zlib_state = SOAP_ZLIB_NONE; + deflateEnd(&soap->d_stream); + } + return soap->error; + } +#else + return soap->error; +#endif +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { int r; + soap->d_stream.avail_in = 0; + do + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating remainder\n")); + r = deflate(&soap->d_stream, Z_FINISH); + if (soap->d_stream.avail_out != SOAP_BUFLEN) + { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN - soap->d_stream.avail_out)) + { soap->zlib_state = SOAP_ZLIB_NONE; + deflateEnd(&soap->d_stream); + return soap->error; + } + soap->d_stream.next_out = (Byte*)soap->z_buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + } + } while (r == Z_OK); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out)); + soap->z_ratio_out = (float)soap->d_stream.total_out / (float)soap->d_stream.total_in; + soap->mode &= ~SOAP_ENC_ZLIB; + soap->zlib_state = SOAP_ZLIB_NONE; + if (deflateEnd(&soap->d_stream) != Z_OK || r != Z_STREAM_END) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to end deflate: %s\n", soap->d_stream.msg?soap->d_stream.msg:"")); + return soap->error = SOAP_ZLIB_ERROR; + } +#ifdef WITH_GZIP + soap->z_buf[0] = soap->z_crc & 0xFF; + soap->z_buf[1] = (soap->z_crc >> 8) & 0xFF; + soap->z_buf[2] = (soap->z_crc >> 16) & 0xFF; + soap->z_buf[3] = (soap->z_crc >> 24) & 0xFF; + soap->z_buf[4] = soap->d_stream.total_in & 0xFF; + soap->z_buf[5] = (soap->d_stream.total_in >> 8) & 0xFF; + soap->z_buf[6] = (soap->d_stream.total_in >> 16) & 0xFF; + soap->z_buf[7] = (soap->d_stream.total_in >> 24) & 0xFF; + if (soap_flush_raw(soap, soap->z_buf, 8)) + return soap->error; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip crc32=%lu\n", (unsigned long)soap->z_crc)); +#endif + } +#endif + if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) + { char *p; +#ifndef WITH_NOHTTP + if (!(soap->mode & SOAP_ENC_XML)) + { soap->mode--; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending buffered message of length %u\n", (unsigned int)soap->blist->size)); + if (soap->status >= SOAP_POST) + soap->error = soap->fpost(soap, soap->endpoint, soap->host, soap->port, soap->path, soap->action, soap->blist->size); + else if (soap->status != SOAP_STOP) + soap->error = soap->fresponse(soap, soap->status, soap->blist->size); + if (soap->error || soap_flush(soap)) + return soap->error; + soap->mode++; + } +#endif + for (p = soap_first_block(soap); p; p = soap_next_block(soap)) + { DBGMSG(SENT, p, soap_block_size(soap)); + if ((soap->error = soap->fsend(soap, p, soap_block_size(soap)))) + { soap_end_block(soap); + return soap->error; + } + } + soap_end_block(soap); + } +#ifndef WITH_LEANER + else if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) + { DBGMSG(SENT, "\r\n0\r\n\r\n", 7); + if ((soap->error = soap->fsend(soap, "\r\n0\r\n\r\n", 7))) + return soap->error; + } +#endif + } +#ifdef WITH_TCPFIN +#ifdef WITH_OPENSSL + if (!soap->ssl && soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP)) + soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 1); /* Send TCP FIN */ +#else + if (soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP)) + soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 1); /* Send TCP FIN */ +#endif +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of send phase\n")); + soap->omode &= ~SOAP_XML_SEC; + soap->count = 0; + soap->part = SOAP_END; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_end_recv(struct soap *soap) +{ soap->part = SOAP_END; +#ifndef WITH_LEANER + if ((soap->mode & SOAP_ENC_DIME) && soap_getdime(soap)) + return soap->error; + soap->dime.list = soap->dime.first; + soap->dime.first = NULL; + soap->dime.last = NULL; + /* Check if MIME attachments and mime-post-check flag is set, if set call soap_resolve() and return */ + if (soap->mode & SOAP_ENC_MIME) + { if (soap->mode & SOAP_MIME_POSTCHECK) + { soap_resolve(soap); + return SOAP_OK; + } + if (soap_getmime(soap)) + return soap->error; + } + soap->mime.list = soap->mime.first; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = NULL; + if (soap->xlist) + { struct soap_multipart *content; + for (content = soap->mime.list; content; content = content->next) + soap_resolve_attachment(soap, content); + } +#endif + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "End of receive message ok\n")); +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { soap->mode &= ~SOAP_ENC_ZLIB; + memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN); + soap->bufidx = (char*)soap->d_stream.next_in - soap->z_buf; + soap->buflen = soap->z_buflen; + soap->zlib_state = SOAP_ZLIB_NONE; + if (inflateEnd(&soap->d_stream) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; +#ifdef WITH_GZIP + if (soap->zlib_in == SOAP_ZLIB_GZIP) + { soap_wchar c; + short i; + for (i = 0; i < 8; i++) + { if ((int)(c = soap_getchar(soap)) == EOF) + return soap->error = SOAP_EOF; + soap->z_buf[i] = (char)c; + } + if (soap->z_crc != ((uLong)(unsigned char)soap->z_buf[0] | ((uLong)(unsigned char)soap->z_buf[1] << 8) | ((uLong)(unsigned char)soap->z_buf[2] << 16) | ((uLong)(unsigned char)soap->z_buf[3] << 24))) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: crc check failed, message corrupted? (crc32=%lu)\n", (unsigned long)soap->z_crc)); + return soap->error = SOAP_ZLIB_ERROR; + } + if (soap->d_stream.total_out != ((uLong)(unsigned char)soap->z_buf[4] | ((uLong)(unsigned char)soap->z_buf[5] << 8) | ((uLong)(unsigned char)soap->z_buf[6] << 16) | ((uLong)(unsigned char)soap->z_buf[7] << 24))) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: incorrect message length\n")); + return soap->error = SOAP_ZLIB_ERROR; + } + } +#endif + } +#endif + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) + while ((int)soap_getchar(soap) != EOF) /* advance to last chunk */ + ; + if (soap->fdisconnect && (soap->error = soap->fdisconnect(soap))) + return soap->error; +#ifndef WITH_NOIDREF + if (soap_resolve(soap)) + return soap->error; +#endif +#ifndef WITH_LEANER + if (soap->xlist) + { if (soap->mode & SOAP_ENC_MTOM) + return soap->error = SOAP_MIME_HREF; + return soap->error = SOAP_DIME_HREF; + } +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_free_temp(struct soap *soap) +{ register struct Namespace *ns; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free namespace stack\n")); + while (soap->nlist) + { register struct soap_nlist *np = soap->nlist->next; + SOAP_FREE(soap, soap->nlist); + soap->nlist = np; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free any remaining temp blocks\n")); + while (soap->blist) + soap_end_block(soap); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute storage\n")); + while (soap->attributes) + { register struct soap_attribute *tp = soap->attributes->next; + if (soap->attributes->value) + SOAP_FREE(soap, soap->attributes->value); + SOAP_FREE(soap, soap->attributes); + soap->attributes = tp; + } +#ifdef WITH_FAST + if (soap->labbuf) + SOAP_FREE(soap, soap->labbuf); + soap->labbuf = NULL; + soap->lablen = 0; + soap->labidx = 0; +#endif + ns = soap->local_namespaces; + if (ns) + { for (; ns->id; ns++) + { if (ns->out) + { if (soap->encodingStyle == ns->out) + soap->encodingStyle = SOAP_STR_EOS; + SOAP_FREE(soap, ns->out); + ns->out = NULL; + } + if (soap->encodingStyle == ns->ns) + soap->encodingStyle = SOAP_STR_EOS; + } + SOAP_FREE(soap, soap->local_namespaces); + soap->local_namespaces = NULL; + } +#ifndef WITH_LEANER + while (soap->xlist) + { struct soap_xlist *xp = soap->xlist->next; + SOAP_FREE(soap, soap->xlist); + soap->xlist = xp; + } +#endif +#ifndef WITH_NOIDREF + soap_free_pht(soap); + soap_free_iht(soap); +#endif +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +static void +soap_init_logs(struct soap *soap) +{ int i; + for (i = 0; i < SOAP_MAXLOGS; i++) + { soap->logfile[i] = NULL; + soap->fdebug[i] = NULL; + } +} +#endif + +/******************************************************************************/ +#if !defined(WITH_LEAN) || defined(SOAP_DEBUG) +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_open_logfile(struct soap *soap, int i) +{ if (soap->logfile[i]) + soap->fdebug[i] = fopen(soap->logfile[i], i < 2 ? "ab" : "a"); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +static void +soap_close_logfile(struct soap *soap, int i) +{ if (soap->fdebug[i]) + { fclose(soap->fdebug[i]); + soap->fdebug[i] = NULL; + } +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_close_logfiles(struct soap *soap) +{ int i; + for (i = 0; i < SOAP_MAXLOGS; i++) + soap_close_logfile(soap, i); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +static void +soap_set_logfile(struct soap *soap, int i, const char *logfile) +{ char *s = NULL; + soap_close_logfile(soap, i); + if (soap->logfile[i]) + SOAP_FREE(soap, (void*)soap->logfile[i]); + if (logfile) + if ((s = (char*)SOAP_MALLOC(soap, strlen(logfile) + 1))) + strcpy(s, logfile); + soap->logfile[i] = s; +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_recv_logfile(struct soap *soap, const char *logfile) +{ soap_set_logfile(soap, SOAP_INDEX_RECV, logfile); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_sent_logfile(struct soap *soap, const char *logfile) +{ soap_set_logfile(soap, SOAP_INDEX_SENT, logfile); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_test_logfile(struct soap *soap, const char *logfile) +{ soap_set_logfile(soap, SOAP_INDEX_TEST, logfile); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_copy(struct soap *soap) +{ return soap_copy_context((struct soap*)malloc(sizeof(struct soap)), soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_copy_context(struct soap *copy, struct soap *soap) +{ if (soap_check_state(soap)) + return NULL; + if (copy) + { register struct soap_plugin *p; + memcpy(copy, soap, sizeof(struct soap)); + copy->state = SOAP_COPY; + copy->error = SOAP_OK; + copy->userid = NULL; + copy->passwd = NULL; + copy->nlist = NULL; + copy->blist = NULL; + copy->clist = NULL; + copy->alist = NULL; + copy->attributes = NULL; + copy->labbuf = NULL; + copy->lablen = 0; + copy->labidx = 0; +#ifdef SOAP_DEBUG + soap_init_mht(copy); +#endif + copy->local_namespaces = NULL; +#ifndef WITH_NOIDREF + soap_init_iht(copy); + soap_init_pht(copy); +#endif + copy->header = NULL; + copy->fault = NULL; + copy->action = NULL; +#ifndef WITH_LEAN +#ifdef WITH_COOKIES + copy->cookies = soap_copy_cookies(copy, soap); +#else + copy->cookies = NULL; +#endif +#endif +#ifdef SOAP_DEBUG + soap_init_logs(copy); + soap_set_recv_logfile(copy, soap->logfile[SOAP_INDEX_RECV]); + soap_set_sent_logfile(copy, soap->logfile[SOAP_INDEX_SENT]); + soap_set_test_logfile(copy, soap->logfile[SOAP_INDEX_TEST]); +#endif + copy->plugins = NULL; + for (p = soap->plugins; p; p = p->next) + { register struct soap_plugin *q = (struct soap_plugin*)SOAP_MALLOC(copy, sizeof(struct soap_plugin)); + if (!q) + return NULL; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying plugin '%s'\n", p->id)); + *q = *p; + if (p->fcopy && (soap->error = p->fcopy(copy, q, p))) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not copy plugin '%s'\n", p->id)); + SOAP_FREE(copy, q); + return NULL; + } + q->next = copy->plugins; + copy->plugins = q; + } + } + else + soap->error = SOAP_EOM; + return copy; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_copy_stream(struct soap *copy, struct soap *soap) +{ copy->mode = soap->mode; + copy->imode = soap->imode; + copy->omode = soap->omode; + copy->socket = soap->socket; + copy->recv_timeout = soap->recv_timeout; + copy->send_timeout = soap->send_timeout; +#if defined(__cplusplus) && !defined(WITH_LEAN) + copy->os = soap->os; + copy->is = soap->is; +#endif + copy->sendfd = soap->sendfd; + copy->recvfd = soap->recvfd; + copy->bufidx = soap->bufidx; + copy->buflen = soap->buflen; + copy->ahead = soap->ahead; + copy->cdata = soap->cdata; + copy->chunksize = soap->chunksize; + copy->chunkbuflen = soap->chunkbuflen; + copy->keep_alive = soap->keep_alive; + copy->max_keep_alive = soap->max_keep_alive; +#ifndef WITH_NOIO + copy->peer = soap->peer; + copy->peerlen = soap->peerlen; +#endif +#ifdef WITH_OPENSSL + copy->bio = soap->bio; + copy->ssl = soap->ssl; + copy->ctx = soap->ctx; +#endif +#ifdef WITH_ZLIB + copy->zlib_state = soap->zlib_state; + copy->zlib_in = soap->zlib_in; + copy->zlib_out = soap->zlib_out; + copy->d_stream = soap->d_stream; + copy->z_buflen = soap->z_buflen; + copy->z_level = soap->z_level; + copy->z_crc = soap->z_crc; + copy->z_ratio_in = soap->z_ratio_in; + copy->z_ratio_out = soap->z_ratio_out; + memcpy(copy->z_buf, soap->z_buf, sizeof(soap->z_buf)); +#endif + memcpy(copy->buf, soap->buf, sizeof(soap->buf)); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_init(struct soap *soap) +{ soap->state = SOAP_INIT; + soap->version = 0; + soap_imode(soap, SOAP_IO_DEFAULT); + soap_omode(soap, SOAP_IO_DEFAULT); + soap->plugins = NULL; + soap->user = NULL; + soap->userid = NULL; + soap->passwd = NULL; +#ifndef WITH_NOHTTP + soap->fpost = http_post; + soap->fget = http_get; + soap->fform = NULL; + soap->fposthdr = http_post_header; + soap->fresponse = http_response; + soap->fparse = http_parse; + soap->fparsehdr = http_parse_header; +#endif + soap->fheader = NULL; + soap->fconnect = NULL; + soap->fdisconnect = NULL; +#ifndef WITH_NOIO +#ifndef WITH_IPV6 + soap->fresolve = tcp_gethost; +#else + soap->fresolve = NULL; +#endif + soap->faccept = tcp_accept; + soap->fopen = tcp_connect; + soap->fclose = tcp_disconnect; + soap->fclosesocket = tcp_closesocket; + soap->fshutdownsocket = tcp_shutdownsocket; + soap->fsend = fsend; + soap->frecv = frecv; + soap->fpoll = soap_poll; +#else + soap->fopen = NULL; + soap->fclose = NULL; + soap->fpoll = NULL; +#endif + soap->fseterror = NULL; + soap->fignore = NULL; + soap->fserveloop = NULL; + soap->fplugin = fplugin; + soap->fmalloc = NULL; +#ifndef WITH_LEANER + soap->fprepareinit = NULL; + soap->fpreparesend = NULL; + soap->fpreparerecv = NULL; + soap->fpreparefinal = NULL; + soap->fdimereadopen = NULL; + soap->fdimewriteopen = NULL; + soap->fdimereadclose = NULL; + soap->fdimewriteclose = NULL; + soap->fdimeread = NULL; + soap->fdimewrite = NULL; + soap->fmimereadopen = NULL; + soap->fmimewriteopen = NULL; + soap->fmimereadclose = NULL; + soap->fmimewriteclose = NULL; + soap->fmimeread = NULL; + soap->fmimewrite = NULL; +#endif + soap->float_format = "%G"; + soap->double_format = "%lG"; + soap->dime_id_format = "cid:id%d"; /* default DIME id format */ + soap->http_version = "1.1"; + soap->proxy_http_version = "1.0"; + soap->http_content = NULL; + soap->actor = NULL; + soap->max_keep_alive = SOAP_MAXKEEPALIVE; + soap->keep_alive = 0; + soap->recv_timeout = 0; + soap->send_timeout = 0; + soap->connect_timeout = 0; + soap->accept_timeout = 0; + soap->socket_flags = 0; + soap->connect_flags = 0; + soap->bind_flags = 0; + soap->accept_flags = 0; + soap->ip = 0; + soap->labbuf = NULL; + soap->lablen = 0; + soap->labidx = 0; + soap->encodingStyle = SOAP_STR_EOS; +#ifndef WITH_NONAMESPACES + soap->namespaces = namespaces; +#else + soap->namespaces = NULL; +#endif + soap->local_namespaces = NULL; + soap->nlist = NULL; + soap->blist = NULL; + soap->clist = NULL; + soap->alist = NULL; + soap->attributes = NULL; + soap->header = NULL; + soap->fault = NULL; + soap->master = SOAP_INVALID_SOCKET; + soap->socket = SOAP_INVALID_SOCKET; + soap->os = NULL; + soap->is = NULL; +#ifndef WITH_LEANER + soap->dom = NULL; + soap->dime.list = NULL; + soap->dime.first = NULL; + soap->dime.last = NULL; + soap->mime.list = NULL; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = NULL; + soap->mime.start = NULL; + soap->xlist = NULL; +#endif +#ifndef UNDER_CE + soap->recvfd = 0; + soap->sendfd = 1; +#else + soap->recvfd = stdin; + soap->sendfd = stdout; +#endif + soap->host[0] = '\0'; + soap->port = 0; + soap->action = NULL; + soap->proxy_host = NULL; + soap->proxy_port = 8080; + soap->proxy_userid = NULL; + soap->proxy_passwd = NULL; + soap->authrealm = NULL; + soap->prolog = NULL; +#ifdef WITH_OPENSSL + if (!ssl_init_done) + soap_ssl_init(); + soap->fsslauth = ssl_auth_init; + soap->fsslverify = ssl_verify_callback; + soap->bio = NULL; + soap->ssl = NULL; + soap->ctx = NULL; + soap->ssl_flags = SOAP_SSL_DEFAULT; + soap->keyfile = NULL; + soap->password = NULL; + soap->dhfile = NULL; + soap->cafile = NULL; + soap->capath = NULL; + soap->crlfile = NULL; + soap->randfile = NULL; + soap->session = NULL; +#endif +#ifdef WITH_ZLIB + soap->zlib_state = SOAP_ZLIB_NONE; + soap->zlib_in = SOAP_ZLIB_NONE; + soap->zlib_out = SOAP_ZLIB_NONE; + soap->d_stream.zalloc = NULL; + soap->d_stream.zfree = NULL; + soap->d_stream.opaque = NULL; + soap->z_level = 6; +#endif +#ifndef WITH_LEAN + soap->c14ninclude = NULL; + soap->c14nexclude = NULL; + soap->cookies = NULL; + soap->cookie_domain = NULL; + soap->cookie_path = NULL; + soap->cookie_max = 32; +#endif +#ifdef SOAP_DEBUG + soap_init_mht(soap); + soap_init_logs(soap); +#endif +#ifdef WMW_RPM_IO + soap->rpmreqid = NULL; +#endif +#ifdef PALM + palmNetLibOpen(); +#endif +#ifndef WITH_NOIDREF + soap_init_iht(soap); + soap_init_pht(soap); +#endif +#ifdef SOAP_DEBUG + soap_set_recv_logfile(soap, "RECV.log"); + soap_set_sent_logfile(soap, "SENT.log"); + soap_set_test_logfile(soap, "TEST.log"); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing context\n")); +#endif + soap_begin(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_init1(struct soap *soap, soap_mode mode) +{ soap_init2(soap, mode, mode); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_init2(struct soap *soap, soap_mode imode, soap_mode omode) +{ soap_init(soap); + soap_imode(soap, imode); + soap_omode(soap, omode); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_begin(struct soap *soap) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reinitializing context\n")); + if (!soap->keep_alive) + { soap->buflen = 0; + soap->bufidx = 0; + } + soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0); + soap->null = 0; + soap->position = 0; + soap->encoding = 0; + soap->mustUnderstand = 0; + soap->mode = 0; + soap->ns = 0; + soap->part = SOAP_END; + soap->alloced = 0; + soap->count = 0; + soap->length = 0; + soap->cdata = 0; + soap->error = SOAP_OK; + soap->peeked = 0; + soap->ahead = 0; + soap->idnum = 0; + soap->level = 0; + soap->endpoint[0] = '\0'; +#ifndef WITH_LEANER + soap->dime.chunksize = 0; + soap->dime.buflen = 0; +#endif + soap_free_temp(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_end(struct soap *soap) +{ register struct soap_clist *cp; + if (soap_check_state(soap)) + return; + soap_free_temp(soap); + soap_dealloc(soap, NULL); + while (soap->clist) + { cp = soap->clist->next; + SOAP_FREE(soap, soap->clist); + soap->clist = cp; + } + soap_closesock(soap); +#ifdef SOAP_DEBUG + soap_close_logfiles(soap); +#endif +#ifdef PALM + palmNetLibClose(); +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_namespaces(struct soap *soap, const struct Namespace *p) +{ register struct Namespace *ns = soap->local_namespaces; + register struct soap_nlist *np, *nq, *nr; + register unsigned int level = soap->level; + soap->namespaces = p; + soap->local_namespaces = NULL; + soap_set_local_namespaces(soap); + /* reverse the namespace list */ + np = soap->nlist; + soap->nlist = NULL; + if (np) + { nq = np->next; + np->next = NULL; + while (nq) + { nr = nq->next; + nq->next = np; + np = nq; + nq = nr; + } + } + /* then push on new stack */ + while (np) + { register const char *s; + soap->level = np->level; /* preserve element nesting level */ + s = np->ns; + if (!s && np->index >= 0 && ns) + { s = ns[np->index].out; + if (!s) + s = ns[np->index].ns; + } + if (s && soap_push_namespace(soap, np->id, s)) + return soap->error; + nq = np; + np = np->next; + SOAP_FREE(soap, nq); + } + if (ns) + { register int i; + for (i = 0; ns[i].id; i++) + { if (ns[i].out) + { SOAP_FREE(soap, ns[i].out); + ns[i].out = NULL; + } + } + SOAP_FREE(soap, ns); + } + soap->level = level; /* restore level */ + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_local_namespaces(struct soap *soap) +{ if (soap->namespaces && !soap->local_namespaces) + { register const struct Namespace *ns1; + register struct Namespace *ns2; + register size_t n = 1; + for (ns1 = soap->namespaces; ns1->id; ns1++) + n++; + n *= sizeof(struct Namespace); + ns2 = (struct Namespace*)SOAP_MALLOC(soap, n); + if (ns2) + { memcpy(ns2, soap->namespaces, n); + if (ns2[0].ns) + { if (!strcmp(ns2[0].ns, soap_env1)) + soap->version = 1; + else + soap->version = 2; + } + soap->local_namespaces = ns2; + } + } +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +#ifndef PALM_1 +SOAP_FMAC1 +const char * +SOAP_FMAC2 +soap_strsearch(const char *big, const char *little) +{ size_t n = strlen(little); + const char *s = big; + while (s) + { if (!strncmp(s, little, n) && (s[n] == '\0' || s[n] == ' ')) + return s; + s = strchr(s, ' '); + if (s) + s++; + } + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +#ifndef PALM_1 +SOAP_FMAC1 +struct soap_nlist * +SOAP_FMAC2 +soap_lookup_ns(struct soap *soap, const char *tag, size_t n) +{ register struct soap_nlist *np; + for (np = soap->nlist; np; np = np->next) + { if (!strncmp(np->id, tag, n) && !np->id[n]) + return np; + } + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static struct soap_nlist * +soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized) +{ register struct soap_nlist *np; + size_t n, k; + if (soap_strsearch(soap->c14nexclude, id)) + return NULL; + if (!utilized) + { for (np = soap->nlist; np; np = np->next) + { if (!strcmp(np->id, id) && (!np->ns || !strcmp(np->ns, ns))) + break; + } + if (np) + { if ((np->level < soap->level || !np->ns) && np->index == 1) + utilized = 1; + else + return NULL; + } + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Adding namespace binding (level=%u) '%s' '%s' utilized=%d\n", soap->level, id, ns?ns:"(null)", utilized)); + n = strlen(id); + if (ns) + k = strlen(ns); + else + k = 0; + np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k + 1); + if (!np) + { soap->error = SOAP_EOM; + return NULL; + } + np->next = soap->nlist; + soap->nlist = np; + strcpy(np->id, id); + if (ns) + { np->ns = np->id + n + 1; + strcpy(np->ns, ns); + } + else + np->ns = NULL; + np->level = soap->level; + np->index = utilized; + return np; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static void +soap_utilize_ns(struct soap *soap, const char *tag, size_t n) +{ register struct soap_nlist *np = soap_lookup_ns(soap, tag, n); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Utilizing namespace of '%s'\n", tag)); + if (np) + { if (np->index == 0) + soap_push_ns(soap, np->id, np->ns, 1); + } + else if (strncmp(tag, "xml", 3)) + { strncpy(soap->tmpbuf, tag, n); + soap->tmpbuf[n] = '\0'; + soap_push_ns(soap, soap->tmpbuf, NULL, 1); + } +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static void +soap_pop_ns(struct soap *soap) +{ soap_pop_namespace(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element(struct soap *soap, const char *tag, int id, const char *type) +{ +#ifdef WITH_XMLNS + register const char *s; +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element begin tag='%s' id='%d' type='%s'\n", tag, id, type?type:"")); +#ifdef WITH_DOM + if (soap->part == SOAP_BEGIN_SECURITY && (soap->mode & SOAP_XML_CANONICAL) && !(soap->mode & SOAP_DOM_ASIS)) + { register struct soap_nlist *np; + /* wsu:Id found: clear xmlns renderings, so re-emit them for exc-c14n */ + for (np = soap->nlist; np; np = np->next) + { if (np->index == 2) + np->index = 0; + } + } + if (soap->mode & SOAP_XML_DOM) + { register struct soap_dom_element *elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element)); + if (!elt) + return soap->error = SOAP_EOM; + elt->soap = soap; + elt->next = NULL; + elt->prnt = soap->dom; + elt->name = soap_strdup(soap, tag); + elt->elts = NULL; + elt->atts = NULL; + elt->nstr = NULL; + elt->data = NULL; + elt->wide = NULL; + elt->node = NULL; + elt->type = 0; + elt->head = NULL; + elt->tail = NULL; + if (soap->dom) + { struct soap_dom_element *p = soap->dom->elts; + if (p) + { while (p->next) + p = p->next; + p->next = elt; + } + else + soap->dom->elts = elt; + } + soap->dom = elt; + } + else + { +#endif + soap->level++; +#ifndef WITH_LEAN + if (!soap->ns) + { if (!(soap->mode & SOAP_XML_CANONICAL) + && soap_send(soap, soap->prolog ? soap->prolog : "\n")) + return soap->error; + } + else if (soap->mode & SOAP_XML_INDENT) + { if (soap->ns == 1 && soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1)) + return soap->error; + soap->body = 1; + } +#endif +#ifdef WITH_XMLNS + s = strchr(tag, ':'); + if (s && strncmp(tag, "SOAP-ENV", s - tag)) + { struct Namespace *ns = soap->local_namespaces; + size_t n = s - tag; + if (soap_send_raw(soap, "<", 1) + || soap_send(soap, s + 1)) + return soap->error; + if (soap->nlist && !strncmp(soap->nlist->id, tag, n) && !soap->nlist->id[n]) + ns = NULL; + for (; ns && ns->id; ns++) + { if (*ns->id && (ns->out || ns->ns) && !strncmp(ns->id, tag, n) && !ns->id[n]) + { soap_push_ns(soap, ns->id, ns->out ? ns->out : ns->ns, 0); + if (soap_attribute(soap, "xmlns", ns->out ? ns->out : ns->ns)) + return soap->error; + break; + } + } + } + else +#endif + if (soap_send_raw(soap, "<", 1) + || soap_send(soap, tag)) + return soap->error; +#ifdef WITH_DOM + } +#endif + if (!soap->ns) + { struct Namespace *ns; + for (ns = soap->local_namespaces; ns && ns->id; ns++) + { if (*ns->id && (ns->out || ns->ns)) + { sprintf(soap->tmpbuf, "xmlns:%s", ns->id); + if (soap_attribute(soap, soap->tmpbuf, ns->out ? ns->out : ns->ns)) + return soap->error; + } + } + } + soap->ns = 1; /* start with 0 or 2, but should be one to continue */ +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { const char *t = strchr(tag, ':'); + if (t) + soap_utilize_ns(soap, tag, t - tag); + } +#endif + if (id > 0) + { sprintf(soap->tmpbuf, "_%d", id); + if (soap_attribute(soap, "id", soap->tmpbuf)) + return soap->error; + } + if (type && *type && (!(soap->mode & SOAP_XML_SEC) || soap->part == SOAP_IN_BODY)) + { if (soap_attribute(soap, "xsi:type", type)) + return soap->error; +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { const char *t = strchr(type, ':'); + if (t) + soap_utilize_ns(soap, type, t - type); + } +#endif + } + if (soap->null && soap->position > 0) + { register int i; + sprintf(soap->tmpbuf, "[%d", soap->positions[0]); + for (i = 1; i < soap->position; i++) + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), ",%d", soap->positions[i]); + strcat(soap->tmpbuf, "]"); + if (soap_attribute(soap, "SOAP-ENC:position", soap->tmpbuf)) + return soap->error; + } + if (soap->mustUnderstand) + { if (soap->actor && *soap->actor) + { if (soap_attribute(soap, soap->version == 2 ? "SOAP-ENV:role" : "SOAP-ENV:actor", soap->actor)) + return soap->error; + } + if (soap_attribute(soap, "SOAP-ENV:mustUnderstand", soap->version == 2 ? "true" : "1")) + return soap->error; + soap->mustUnderstand = 0; + } + if (soap->encoding) + { if (soap->encodingStyle && soap->local_namespaces) + { if (!*soap->encodingStyle) + { if (soap->local_namespaces[1].out) + soap->encodingStyle = soap->local_namespaces[1].out; + else + soap->encodingStyle = soap->local_namespaces[1].ns; + } + if (soap_attribute(soap, "SOAP-ENV:encodingStyle", soap->encodingStyle)) + return soap->error; + } + soap->encoding = 0; + } + soap->null = 0; + soap->position = 0; + if (soap->part == SOAP_BEGIN_SECURITY && (soap->mode & SOAP_XML_CANONICAL)) + soap->part = SOAP_IN_SECURITY; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_begin_out(struct soap *soap, const char *tag, int id, const char *type) +{ if (*tag == '-') + return SOAP_OK; + if (soap_element(soap, tag, id, type)) + return soap->error; + return soap_element_start_end_out(soap, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +#ifndef HAVE_STRRCHR +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_strrchr(const char *s, int t) +{ register char *r = NULL; + while (*s) + if (*s++ == t) + r = (char*)s - 1; + return r; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +#ifndef HAVE_STRTOL +SOAP_FMAC1 +long +SOAP_FMAC2 +soap_strtol(const char *s, char **t, int b) +{ register long n = 0; + register int c; + while (*s > 0 && *s <= 32) + s++; + if (b == 10) + { short neg = 0; + if (*s == '-') + { s++; + neg = 1; + } + else if (*s == '+') + s++; + while ((c = *s) && c >= '0' && c <= '9') + { if (n >= 214748364 && (n > 214748364 || c >= '8')) + break; + n *= 10; + n += c - '0'; + s++; + } + if (neg) + n = -n; + } + else /* b == 16 and value is always positive */ + { while ((c = *s)) + { if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'F') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'f') + c -= 'a' - 10; + if (n > 0x07FFFFFF) + break; + n <<= 4; + n += c; + s++; + } + } + if (t) + *t = (char*)s; + return n; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +#ifndef HAVE_STRTOUL +SOAP_FMAC1 +unsigned long +SOAP_FMAC2 +soap_strtoul(const char *s, char **t, int b) +{ unsigned long n = 0; + register int c; + while (*s > 0 && *s <= 32) + s++; + if (b == 10) + { if (*s == '+') + s++; + while ((c = *s) && c >= '0' && c <= '9') + { if (n >= 429496729 && (n > 429496729 || c >= '6')) + break; + n *= 10; + n += c - '0'; + s++; + } + } + else /* b == 16 */ + { while ((c = *s)) + { if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'F') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'f') + c -= 'a' - 10; + if (n > 0x0FFFFFFF) + break; + n <<= 4; + n += c; + s++; + } + } + if (t) + *t = (char*)s; + return n; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_array_begin_out(struct soap *soap, const char *tag, int id, const char *type, const char *offset) +{ if (soap_element(soap, tag, id, "SOAP-ENC:Array")) + return soap->error; + if (soap->version == 2) + { const char *s; + s = soap_strrchr(type, '['); + if ((size_t)(s - type) < sizeof(soap->tmpbuf)) + { strncpy(soap->tmpbuf, type, s - type); + soap->tmpbuf[s - type] = '\0'; + if (type && *type && (soap_attribute(soap, "SOAP-ENC:itemType", soap->tmpbuf))) + return soap->error; + if (s && (soap_attribute(soap, "SOAP-ENC:arraySize", s + 1))) + return soap->error; + } + } + else + { if (offset && (soap_attribute(soap, "SOAP-ENC:offset", offset))) + return soap->error; + if (type && *type && (soap_attribute(soap, "SOAP-ENC:arrayType", type))) + return soap->error; + } +#ifndef WITH_LEAN + if (type && *type && (soap->mode & SOAP_XML_CANONICAL)) + { const char *s = strchr(type, ':'); + if (s) + soap_utilize_ns(soap, type, s - type); + } +#endif + return soap_element_start_end_out(soap, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_start_end_out(struct soap *soap, const char *tag) +{ register struct soap_attribute *tp; +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { struct soap_nlist *np; + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible && tp->name) + { const char *s = strchr(tp->name, ':'); + if (s) + soap_utilize_ns(soap, tp->name, s - tp->name); + } + } + for (np = soap->nlist; np; np = np->next) + { if (np->index == 1 && np->ns) + { sprintf(soap->tmpbuf, "xmlns:%s", np->id); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enabling utilized binding (level=%u) %s='%s'\n", np->level, soap->tmpbuf, np->ns)); + soap_set_attr(soap, soap->tmpbuf, np->ns); + np->index = 2; + } + } + } +#endif +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { register struct soap_dom_attribute **att; + att = &soap->dom->atts; + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible) + { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); + if (!*att) + return soap->error = SOAP_EOM; + (*att)->next = NULL; + (*att)->nstr = NULL; + (*att)->name = soap_strdup(soap, tp->name); + (*att)->data = soap_strdup(soap, tp->value); + (*att)->wide = NULL; + (*att)->soap = soap; + att = &(*att)->next; + tp->visible = 0; + } + } + return SOAP_OK; + } +#endif + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible) + { +#ifdef WITH_XMLNS + const char *s = strchr(tp->name, ':'); + if (s) + { size_t n = s - tp->name; + if (soap->nlist && !strncmp(soap->nlist->id, tp->name, n) && !soap->nlist->id[n]) + s++; + else + s = tp->name; + if (soap_send(soap, " ") || soap_send(soap, s)) + return soap->error; + } + else +#endif + if (soap_send(soap, " ") || soap_send(soap, tp->name)) + return soap->error; + if (tp->visible == 2 && tp->value) + if (soap_send_raw(soap, "=\"", 2) + || soap_string_out(soap, tp->value, 1) + || soap_send_raw(soap, "\"", 1)) + return soap->error; + tp->visible = 0; + } + } + if (tag) + { +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { if (soap_send_raw(soap, ">", 1) + || soap_element_end_out(soap, tag)) + return soap->error; + return SOAP_OK; + } +#endif + soap->level--; /* decrement level just before /> */ + if (soap_send_raw(soap, "/>", 2)) + return soap->error; + return SOAP_OK; + } + return soap_send_raw(soap, ">", 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_end_out(struct soap *soap, const char *tag) +{ if (*tag == '-') + return SOAP_OK; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element ending tag='%s'\n", tag)); +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { if (soap->dom->prnt) + soap->dom = soap->dom->prnt; + return SOAP_OK; + } +#endif +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + soap_pop_ns(soap); + if (soap->mode & SOAP_XML_INDENT) + { if (!soap->body) + { if (soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1)) + return soap->error; + } + soap->body = 0; + } +#endif +#ifdef WITH_XMLNS + { const char *s = strchr(tag, ':'); + if (s && strncmp(tag, "SOAP-ENV", s - tag)) + { soap_pop_ns(soap); + tag = s + 1; + } + } +#endif + if (soap_send_raw(soap, "error; + soap->level--; /* decrement level just before > */ + return soap_send_raw(soap, ">", 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_ref(struct soap *soap, const char *tag, int id, int href) +{ register int n = 0; + const char *s = "href"; + if (soap->version == 2) + { s = "SOAP-ENC:ref"; + n = 1; + } + sprintf(soap->href, "#_%d", href); + return soap_element_href(soap, tag, id, s, soap->href + n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_href(struct soap *soap, const char *tag, int id, const char *ref, const char *val) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element '%s' reference %s='%s'\n", tag, ref, val)); + if (soap_element(soap, tag, id, NULL) + || soap_attribute(soap, ref, val) + || soap_element_start_end_out(soap, tag)) + return soap->error; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_null(struct soap *soap, const char *tag, int id, const char *type) +{ struct soap_attribute *tp; + for (tp = soap->attributes; tp; tp = tp->next) + if (tp->visible) + break; + if (tp || (soap->version == 2 && soap->position > 0) || id > 0 || (soap->mode & SOAP_XML_NIL)) + { if (soap_element(soap, tag, id, type)) + return soap->error; + if (soap->part != SOAP_IN_HEADER && soap->encodingStyle) + if (soap_attribute(soap, "xsi:nil", "true")) + return soap->error; + return soap_element_start_end_out(soap, tag); + } + soap->null = 1; + soap->position = 0; + soap->mustUnderstand = 0; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_id(struct soap *soap, const char *tag, int id, const void *p, const struct soap_array *a, int n, const char *type, int t) +{ if (!p || (a && !a->__ptr)) + { soap_element_null(soap, tag, id, type); + return -1; + } +#ifndef WITH_NOIDREF + if (soap->mode & SOAP_XML_TREE) + return 0; + if (id < 0) + { struct soap_plist *pp; + if (a) + id = soap_array_pointer_lookup(soap, p, a, n, t, &pp); + else + id = soap_pointer_lookup(soap, p, t, &pp); + if (id) + { if (soap_is_embedded(soap, pp)) + { soap_element_ref(soap, tag, 0, id); + return -1; + } + if (soap_is_single(soap, pp)) + return 0; + soap_set_embedded(soap, pp); + } + } + return id; +#else + return 0; +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_result(struct soap *soap, const char *tag) +{ if (soap->version == 2 && soap->encodingStyle) + if (soap_element(soap, "SOAP-RPC:result", 0, NULL) + || soap_attribute(soap, "xmlns:SOAP-RPC", soap_rpc) + || soap_element_start_end_out(soap, NULL) + || soap_string_out(soap, tag, 0) + || soap_element_end_out(soap, "SOAP-RPC:result")) + return soap->error; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_check_result(struct soap *soap, const char *tag) +{ if (soap->version == 2 && soap->encodingStyle) + { soap_instring(soap, ":result", NULL, NULL, 0, 2, -1, -1); + /* should compare tag to element's QName value? */ + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_attribute(struct soap *soap, const char *name, const char *value) +{ +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && !(soap->mode & SOAP_XML_CANONICAL) && soap->dom) + { register struct soap_dom_attribute *a = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); + a->next = soap->dom->atts; + a->nstr = NULL; + a->name = soap_strdup(soap, name); + a->data = soap_strdup(soap, value); + a->wide = NULL; + a->soap = soap; + soap->dom->atts = a; + return SOAP_OK; + } +#endif +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { /* TODO: consider using this code to handle default namespace bindings + if (!strncmp(name, "xmlns", 5) && (name[5] == ':' || name[5] == '\0')) + { if (name[5] == ':') + soap_push_ns(soap, name + 6, value, 0); + else + soap_push_ns(soap, "", value, 0); + } + */ + if (!strncmp(name, "xmlns:", 6)) + soap_push_ns(soap, name + 6, value, 0); + else if (soap_set_attr(soap, name, value)) + return soap->error; + } + else +#endif + { if (soap_send(soap, " ") || soap_send(soap, name)) + return soap->error; + if (value) + if (soap_send_raw(soap, "=\"", 2) + || soap_string_out(soap, value, 1) + || soap_send_raw(soap, "\"", 1)) + return soap->error; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_begin_in(struct soap *soap, const char *tag, int nillable, const char *type) +{ if (!soap_peek_element(soap)) + { if (soap->other) + return soap->error = SOAP_TAG_MISMATCH; + if (tag && *tag == '-') + return SOAP_OK; + if (!(soap->error = soap_match_tag(soap, soap->tag, tag))) + { soap->peeked = 0; + if (soap->body) + soap->level++; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:"" )); + if (!nillable && soap->null && (soap->mode & SOAP_XML_STRICT)) + return soap->error = SOAP_NULL; + if (type && *soap->type && soap_match_tag(soap, soap->type, type)) + return soap->error = SOAP_TYPE; + } + } + else if (soap->error == SOAP_NO_TAG && tag && *tag == '-') + soap->error = SOAP_OK; + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_end_in(struct soap *soap, const char *tag) +{ register soap_wchar c; + register char *s; + register const char *t; + register int n = 0; + if (tag && *tag == '-') + return SOAP_OK; + soap->level--; + soap_pop_namespace(soap); +#ifdef WITH_DOM + /* this whitespace or mixed content is not insignificant for DOM */ + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { if (!soap->peeked && !soap_string_in(soap, 3, -1, -1)) + return soap->error; + if (soap->dom->prnt) + soap->dom = soap->dom->prnt; + } +#endif + if (soap->peeked) + { if (soap->error == SOAP_NO_TAG) + soap->error = SOAP_OK; + if (*soap->tag) + n++; + soap->peeked = 0; + } + do + { while (((c = soap_get(soap)) != SOAP_TT)) + { if ((int)c == EOF) + return soap->error = SOAP_EOF; + if (c == SOAP_LT) + n++; + else if (c == '/') + { c = soap_get(soap); + if (c == SOAP_GT) + n--; + else + soap_unget(soap, c); + } + } + } while (n--); + s = soap->tag; + n = sizeof(soap->tag); + while (soap_notblank(c = soap_get(soap))) + { if (--n > 0) + *s++ = (char)c; + } + *s = '\0'; + if ((int)c == EOF) + return soap->error = SOAP_EOF; + while (soap_blank(c)) + c = soap_get(soap); + if (c != SOAP_GT) + return soap->error = SOAP_SYNTAX_ERROR; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:"")); + if (!tag || !*tag) + return SOAP_OK; + if ((s = strchr(soap->tag, ':'))) + s++; + else + s = soap->tag; + if ((t = strchr(tag, ':'))) + t++; + else + t = tag; + if (!SOAP_STRCMP(s, t)) + return SOAP_OK; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element tag name does not match\n")); + return soap->error = SOAP_SYNTAX_ERROR; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char * +SOAP_FMAC2 +soap_attr_value(struct soap *soap, const char *name, int flag) +{ register struct soap_attribute *tp; + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible && !soap_match_tag(soap, tp->name, name)) + break; + } + if (tp) + { if (flag == 2 && (soap->mode & SOAP_XML_STRICT)) + soap->error = SOAP_PROHIBITED; + else + return tp->value; + } + else if (flag == 1 && (soap->mode & SOAP_XML_STRICT)) + soap->error = SOAP_REQUIRED; + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_attr(struct soap *soap, const char *name, const char *value) +{ register struct soap_attribute *tp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set attribute %s='%s'\n", name, value?value:"")); + for (tp = soap->attributes; tp; tp = tp->next) + { if (!strcmp(tp->name, name)) + break; + } + if (!tp) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute %s\n", name)); + if (!(tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(name)))) + return soap->error = SOAP_EOM; + tp->ns = NULL; +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { struct soap_attribute **tpp = &soap->attributes; + const char *s = strchr(name, ':'); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inserting attribute %s for c14n\n", name)) + if (!strncmp(name, "xmlns", 5)) + { for (; *tpp; tpp = &(*tpp)->next) + if (strncmp((*tpp)->name, "xmlns", 5) || strcmp((*tpp)->name + 5, name + 5) > 0) + break; + } + else if (!s) + { for (; *tpp; tpp = &(*tpp)->next) + if (strncmp((*tpp)->name, "xmlns", 5) && ((*tpp)->ns || strcmp((*tpp)->name, name) > 0)) + break; + } + else + { int k; + for (; *tpp; tpp = &(*tpp)->next) + { if (!strncmp((*tpp)->name, "xmlns:", 6) && !strncmp((*tpp)->name + 6, name, s - name) && !(*tpp)->name[6 + s - name]) + { if (!tp->ns) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Canonicalization: prefix %s=%p (%s)\n", name, (*tpp)->ns, (*tpp)->ns)); + tp->ns = (*tpp)->ns; + } + } + else if (strncmp((*tpp)->name, "xmlns", 5) && (*tpp)->ns && tp->ns && ((k = strcmp((*tpp)->ns, tp->ns)) > 0 || (!k && strcmp((*tpp)->name, name) > 0))) + break; + } + } + tp->next = *tpp; + *tpp = tp; + } + else +#endif + { tp->next = soap->attributes; + soap->attributes = tp; + } + strcpy(tp->name, name); + tp->value = NULL; + } + else if (tp->visible) + { return SOAP_OK; + } + else if (value && tp->value && tp->size <= strlen(value)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute value of %s (free %p)\n", name, tp->value)); + SOAP_FREE(soap, tp->value); + tp->value = NULL; + tp->ns = NULL; + } + if (value) + { if (!tp->value) + { tp->size = strlen(value) + 1; + if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size))) + return soap->error = SOAP_EOM; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute value for %s (%p)\n", tp->name, tp->value)); + } + strcpy(tp->value, value); + if (!strncmp(tp->name, "xmlns:", 6)) + tp->ns = tp->value; + tp->visible = 2; +#ifndef WITH_LEAN + if (!strcmp(name, "wsu:Id")) + { soap->part = SOAP_BEGIN_SECURITY; + strncpy(soap->id, value, sizeof(soap->id)); + soap->id[sizeof(soap->id)-1] = '\0'; + } +#endif + } + else + tp->visible = 1; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_clr_attr(struct soap *soap) +{ register struct soap_attribute *tp; +#ifndef WITH_LEAN + if ((soap->mode & SOAP_XML_CANONICAL)) + { while (soap->attributes) + { tp = soap->attributes->next; + if (soap->attributes->value) + SOAP_FREE(soap, soap->attributes->value); + SOAP_FREE(soap, soap->attributes); + soap->attributes = tp; + } + } + else +#endif + { for (tp = soap->attributes; tp; tp = tp->next) + tp->visible = 0; + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +static int +soap_getattrval(struct soap *soap, char *s, size_t n, soap_wchar d) +{ register size_t i; + for (i = 0; i < n; i++) + { register soap_wchar c = soap_get(soap); + switch (c) + { + case SOAP_TT: + *s++ = '<'; + soap_unget(soap, '/'); + break; + case SOAP_LT: + *s++ = '<'; + break; + case SOAP_GT: + if (d == ' ') + { soap_unget(soap, c); + *s = '\0'; + return SOAP_OK; + } + *s++ = '>'; + break; + case SOAP_QT: + if (c == d) + { *s = '\0'; + return SOAP_OK; + } + *s++ = '"'; + break; + case SOAP_AP: + if (c == d) + { *s = '\0'; + return SOAP_OK; + } + *s++ = '\''; + break; + case '\t': + case '\n': + case '\r': + case ' ': + case '/': + if (d == ' ') + { soap_unget(soap, c); + *s = '\0'; + return SOAP_OK; + } + default: + if ((int)c == EOF) + return soap->error = SOAP_EOF; + *s++ = (char)c; + } + } + return soap->error = SOAP_EOM; +} +#endif + +/******************************************************************************/ +#ifdef WITH_FAST +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_store_lab(struct soap *soap, const char *s, size_t n) +{ soap->labidx = 0; + return soap_append_lab(soap, s, n); +} +#endif +#endif + +/******************************************************************************/ +#ifdef WITH_FAST +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_append_lab(struct soap *soap, const char *s, size_t n) +{ if (soap->labidx + n >= soap->lablen) + { register char *t = soap->labbuf; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enlarging look-aside buffer to append data, old size=%lu", (unsigned long)soap->lablen)); + if (soap->lablen == 0) + soap->lablen = SOAP_LABLEN; + while (soap->labidx + n >= soap->lablen) + soap->lablen <<= 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, ", new size=%lu\n", (unsigned long)soap->lablen)); + soap->labbuf = (char*)SOAP_MALLOC(soap, soap->lablen); + if (!soap->labbuf) + { if (t) + SOAP_FREE(soap, t); + return soap->error = SOAP_EOM; + } + if (t) + { memcpy(soap->labbuf, t, soap->labidx); + SOAP_FREE(soap, t); + } + } + if (s) + { memcpy(soap->labbuf + soap->labidx, s, n); + soap->labidx += n; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_peek_element(struct soap *soap) +{ +#ifdef WITH_DOM + register struct soap_dom_attribute **att = NULL; + register char *lead = NULL; +#endif + register struct soap_attribute *tp; + const char *t; + register char *s; + register soap_wchar c; + register int i; + if (soap->peeked) + { if (!*soap->tag) + return soap->error = SOAP_NO_TAG; + return SOAP_OK; + } + soap->peeked = 1; + c = soap_getutf8(soap); +#ifdef WITH_DOM + /* whitespace leading to start tag is not insignificant for DOM */ + if (soap_blank(c)) + { soap->labidx = 0; + do + { if (soap_append_lab(soap, NULL, 0)) + return SOAP_EOM; + s = soap->labbuf + soap->labidx; + i = soap->lablen - soap->labidx; + soap->labidx = soap->lablen; + while (soap_blank(c) && i--) + { *s++ = c; + c = soap_getutf8(soap); + } + } + while (soap_blank(c)); + *s = '\0'; + lead = soap_strdup(soap, soap->labbuf); + } +#else + while (soap_blank(c)) + c = soap_getutf8(soap); +#endif + if (c != SOAP_LT) + { *soap->tag = '\0'; + if ((int)c == EOF) + return soap->error = SOAP_EOF; + soap_unget(soap, c); +#ifdef WITH_DOM + /* whitespace leading to end tag is not insignificant for DOM */ + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + soap->dom->tail = soap_strdup(soap, lead); +#endif + return soap->error = SOAP_NO_TAG; + } + s = soap->tag; + do c = soap_get1(soap); + while (soap_blank(c)); + i = sizeof(soap->tag); + while (c != '>' && c != '/' && soap_notblank(c) && (int)c != EOF) + { if (--i > 0) + *s++ = (char)c; + c = soap_get1(soap); + } + while (soap_blank(c)) + c = soap_get1(soap); + *s = '\0'; + soap->id[0] = '\0'; + soap->href[0] = '\0'; + soap->type[0] = '\0'; + soap->arrayType[0] = '\0'; + soap->arraySize[0] = '\0'; + soap->arrayOffset[0] = '\0'; + soap->other = 0; + soap->root = -1; + soap->position = 0; + soap->null = 0; + soap->mustUnderstand = 0; +#ifdef WITH_DOM + if (soap->mode & SOAP_XML_DOM) + { register struct soap_dom_element *elt; + elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element)); + if (!elt) + return soap->error = SOAP_EOM; + elt->next = NULL; + elt->nstr = NULL; + elt->name = soap_strdup(soap, soap->tag); + elt->prnt = soap->dom; + elt->elts = NULL; + elt->atts = NULL; + elt->data = NULL; + elt->wide = NULL; + elt->type = 0; + elt->node = NULL; + elt->head = lead; + elt->tail = NULL; + elt->soap = soap; + if (soap->dom) + { struct soap_dom_element *p = soap->dom->elts; + if (p) + { while (p->next) + p = p->next; + p->next = elt; + } + else + soap->dom->elts = elt; + } + soap->dom = elt; + att = &elt->atts; + } +#endif + for (tp = soap->attributes; tp; tp = tp->next) + tp->visible = 0; + while ((int)c != EOF && c != '>' && c != '/') + { s = soap->tmpbuf; + i = sizeof(soap->tmpbuf); + while (c != '=' && c != '>' && c != '/' && soap_notblank(c) && (int)c != EOF) + { if (--i > 0) + *s++ = (char)c; + c = soap_get1(soap); + } + *s = '\0'; + if (i == sizeof(soap->tmpbuf)) + return soap->error = SOAP_SYNTAX_ERROR; +#ifdef WITH_DOM + /* add attribute name to dom */ + if (att) + { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); + if (!*att) + return soap->error = SOAP_EOM; + (*att)->next = NULL; + (*att)->nstr = NULL; + (*att)->name = soap_strdup(soap, soap->tmpbuf); + (*att)->data = NULL; + (*att)->wide = NULL; + (*att)->soap = soap; + } +#endif + if (!strncmp(soap->tmpbuf, "xmlns", 5)) + { if (soap->tmpbuf[5] == ':') + { soap->tmpbuf[5] = '\0'; + t = soap->tmpbuf + 6; + } + else if (soap->tmpbuf[5]) + t = NULL; + else + t = SOAP_STR_EOS; + } + else + t = NULL; + for (tp = soap->attributes; tp; tp = tp->next) + { if (!SOAP_STRCMP(tp->name, soap->tmpbuf)) + break; + } + if (!tp) + { tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(soap->tmpbuf)); + if (!tp) + return soap->error = SOAP_EOM; + strcpy(tp->name, soap->tmpbuf); + tp->value = NULL; + tp->size = 0; + tp->next = soap->attributes; + soap->attributes = tp; + } + while (soap_blank(c)) + c = soap_get1(soap); + if (c == '=') + { do c = soap_getutf8(soap); + while (soap_blank(c)); + if (c != SOAP_QT && c != SOAP_AP) + { soap_unget(soap, c); + c = ' '; /* blank delimiter */ + } + if (soap_getattrval(soap, tp->value, tp->size, c)) + { +#ifdef WITH_FAST + if (soap->error != SOAP_EOM) + return soap->error; + soap->error = SOAP_OK; + if (soap_store_lab(soap, tp->value, tp->size)) + return soap->error; + if (tp->value) + SOAP_FREE(soap, tp->value); + for (;;) + { if (soap_getattrval(soap, soap->labbuf + soap->labidx, soap->lablen - soap->labidx, c)) + { if (soap->error != SOAP_EOM) + return soap->error; + soap->error = SOAP_OK; + soap->labidx = soap->lablen; + if (soap_append_lab(soap, NULL, 0)) + return soap->error; + } + else + break; + } + if (soap->labidx) + tp->size = soap->lablen; + else + { tp->size = strlen(soap->labbuf) + 1; + if (tp->size < SOAP_LABLEN) + tp->size = SOAP_LABLEN; + } + if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size))) + return soap->error = SOAP_EOM; + strcpy(tp->value, soap->labbuf); +#else + size_t n; + if (soap->error != SOAP_EOM) + return soap->error; + soap->error = SOAP_OK; + if (soap_new_block(soap)) + return soap->error; + for (;;) + { if (!(s = (char*)soap_push_block(soap, SOAP_BLKLEN))) + return soap->error; + if (soap_getattrval(soap, s, SOAP_BLKLEN, c)) + { if (soap->error != SOAP_EOM) + return soap->error; + soap->error = SOAP_OK; + } + else + break; + } + n = tp->size + soap->blist->size; + if (!(s = (char*)SOAP_MALLOC(soap, n))) + return soap->error = SOAP_EOM; + if (tp->value) + { memcpy(s, tp->value, tp->size); + SOAP_FREE(soap, tp->value); + } + soap_save_block(soap, s + tp->size, 0); + tp->value = s; + tp->size = n; +#endif + } + do c = soap_get1(soap); + while (soap_blank(c)); + tp->visible = 2; /* seen this attribute w/ value */ +#ifdef WITH_DOM + if (att) + (*att)->data = soap_strdup(soap, tp->value); +#endif + } + else + tp->visible = 1; /* seen this attribute w/o value */ +#ifdef WITH_DOM + if (att) + att = &(*att)->next; +#endif + if (t && tp->value) + { if (soap_push_namespace(soap, t, tp->value)) + return soap->error; + tp->visible = 0; + } + } +#ifdef WITH_DOM + if (att) + { soap->dom->nstr = soap_current_namespace(soap, soap->tag); + for (att = &soap->dom->atts; *att; att = &(*att)->next) + (*att)->nstr = soap_current_namespace(soap, (*att)->name); + } +#endif + if ((int)c == EOF) + return soap->error = SOAP_EOF; + if (!(soap->body = (c != '/'))) + do c = soap_get1(soap); + while (soap_blank(c)); +#ifdef WITH_DOM + if (soap->mode & SOAP_XML_DOM) + { if (!soap->body && soap->dom->prnt) + soap->dom = soap->dom->prnt; + } +#endif + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible && tp->value) + { if (!strcmp(tp->name, "id")) + { if (soap->version > 0 + || (soap->mode & SOAP_XML_GRAPH)) + { *soap->id = '#'; + strncpy(soap->id + 1, tp->value, sizeof(soap->id) - 2); + soap->id[sizeof(soap->id)-1] = '\0'; + } + } + else if (!strcmp(tp->name, "href")) + { if (soap->version == 1 + || (soap->mode & SOAP_XML_GRAPH) + || (soap->mode & SOAP_ENC_MTOM)) + { strncpy(soap->href, tp->value, sizeof(soap->href) - 1); + soap->href[sizeof(soap->href)-1] = '\0'; + } + } + else if (!soap_match_tag(soap, tp->name, "xsi:type")) + { strncpy(soap->type, tp->value, sizeof(soap->type) - 1); + soap->type[sizeof(soap->type)-1] = '\0'; + } + else if ((!soap_match_tag(soap, tp->name, "xsi:null") + || !soap_match_tag(soap, tp->name, "xsi:nil")) + && (!strcmp(tp->value, "1") + || !strcmp(tp->value, "true"))) + { soap->null = 1; + } + else if (soap->version == 1) + { if (!soap_match_tag(soap, tp->name, "SOAP-ENC:arrayType")) + { s = soap_strrchr(tp->value, '['); + if (s && (size_t)(s - tp->value) < sizeof(soap->arrayType)) + { strncpy(soap->arrayType, tp->value, s - tp->value); + soap->arrayType[s - tp->value] = '\0'; + strncpy(soap->arraySize, s, sizeof(soap->arraySize) - 1); + } + else + strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1); + soap->arraySize[sizeof(soap->arrayType)-1] = '\0'; + soap->arrayType[sizeof(soap->arrayType)-1] = '\0'; + } + else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:offset")) + strncpy(soap->arrayOffset, tp->value, sizeof(soap->arrayOffset)); + else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:position")) + soap->position = soap_getposition(tp->value, soap->positions); + else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:root")) + soap->root = ((!strcmp(tp->value, "1") || !strcmp(tp->value, "true"))); + else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand") + && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true"))) + soap->mustUnderstand = 1; + else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:actor")) + { if ((!soap->actor || strcmp(soap->actor, tp->value)) + && strcmp(tp->value, "http://schemas.xmlsoap.org/soap/actor/next")) + soap->other = 1; + } + } + else if (soap->version == 2) + { if (!strcmp(tp->name, "ref") + || !soap_match_tag(soap, tp->name, "SOAP-ENC:ref")) + { *soap->href = '#'; + strncpy(soap->href + 1, tp->value, sizeof(soap->href) - 2); + soap->href[sizeof(soap->href)-1] = '\0'; + } + else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:itemType")) + strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1); + else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:arraySize")) + strncpy(soap->arraySize, tp->value, sizeof(soap->arraySize) - 1); + else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand") + && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true"))) + soap->mustUnderstand = 1; + else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:role")) + { if ((!soap->actor || strcmp(soap->actor, tp->value)) + && strcmp(tp->value, "http://www.w3.org/2003/05/soap-envelope/role/next")) + soap->other = 1; + } + } + } + } + return soap->error = SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_retry(struct soap *soap) +{ soap->error = SOAP_OK; + soap_revert(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_revert(struct soap *soap) +{ if (!soap->peeked) + { soap->peeked = 1; + if (soap->body) + soap->level--; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reverting last element (level=%u)\n", soap->level)); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_string_out(struct soap *soap, const char *s, int flag) +{ register const char *t; + register soap_wchar c; + register soap_wchar mask = 0xFFFFFF80UL; +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { soap->dom->data = soap_strdup(soap, s); + return SOAP_OK; + } +#endif + if (soap->mode & SOAP_C_UTFSTRING) + mask = 0; + t = s; + while ((c = *t++)) + { switch (c) + { + case 0x09: + if (flag) + { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, " ", 5)) + return soap->error; + s = t; + } + break; + case 0x0A: + if (flag || !(soap->mode & SOAP_XML_CANONICAL)) + { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, " ", 5)) + return soap->error; + s = t; + } + break; + case 0x0D: + if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, " ", 5)) + return soap->error; + s = t; + break; + case '&': + if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&", 5)) + return soap->error; + s = t; + break; + case '<': + if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "<", 4)) + return soap->error; + s = t; + break; + case '>': + if (!flag) + { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, ">", 4)) + return soap->error; + s = t; + } + break; + case '"': + if (flag) + { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, """, 6)) + return soap->error; + s = t; + } + break; + default: +#ifndef WITH_LEANER +#ifdef HAVE_MBTOWC + if (soap->mode & SOAP_C_MBSTRING) + { wchar_t wc; + register int m = mbtowc(&wc, t - 1, MB_CUR_MAX); + if (m > 0 && wc != c) + { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, wc)) + return soap->error; + s = t += m - 1; + continue; + } + } +#endif +#endif + if ((c & mask) || !(c & 0xFFFFFFE0UL)) + { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned char)c)) + return soap->error; + s = t; + } + } + } + return soap_send_raw(soap, s, t - s - 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_string_in(struct soap *soap, int flag, long minlen, long maxlen) +{ register char *s; + char *t = NULL; + register size_t i; + register long l = 0; + register int n = 0; + register int m = 0; + register soap_wchar c; +#if !defined(WITH_LEANER) && defined(HAVE_WCTOMB) + char buf[MB_LEN_MAX > 8 ? MB_LEN_MAX : 8]; +#else + char buf[8]; +#endif + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading string content\n")); + if (soap->peeked) + { if (!soap->body) + return NULL; + if (*soap->tag) + { n = 1; + soap->peeked = 0; +#ifndef WITH_LEAN + t = soap->tmpbuf; + t[0] = '<'; + strncpy(t + 1, soap->tag, sizeof(soap->tmpbuf) - 1); + strncat(t, ">", sizeof(soap->tmpbuf)); + m = strlen(soap->tag) + 2; +#endif + } + } +#ifdef WITH_CDATA + if (!flag) + { register int state = 0; +#ifdef WITH_FAST + soap->labidx = 0; /* use look-aside buffer */ +#else + if (soap_new_block(soap)) + return NULL; +#endif + for (;;) + { +#ifdef WITH_FAST + register size_t k; + if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */ + return NULL; + s = soap->labbuf + soap->labidx; /* space to populate */ + k = soap->lablen - soap->labidx; /* number of bytes available */ + soap->labidx = soap->lablen; /* claim this space */ +#else + register size_t k = SOAP_BLKLEN; + if (!(s = (char*)soap_push_block(soap, k))) + return NULL; +#endif + for (i = 0; i < k; i++) + { if (m > 0) + { *s++ = *t++; /* copy multibyte characters */ + m--; + continue; + } + c = soap_getchar(soap); + if ((int)c == EOF) + goto end; + if (c >= 0x80 && !(soap->mode & SOAP_ENC_LATIN)) + { soap_unget(soap, c); + c = soap_getutf8(soap); + if (soap->mode & SOAP_C_UTFSTRING) + { if ((c & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP) + { c &= 0x7FFFFFFF; + t = buf; + if (c < 0x0800) + *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); + else + { if (c < 0x010000) + *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + else + { if (c < 0x200000) + *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + else + { if (c < 0x04000000) + *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + else + { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + } + *t++ = (char)(0x80 | (c & 0x3F)); + m = (int)(t - buf) - 1; + t = buf; + *s++ = *t++; + continue; + } + } + } + switch (state) + { case 1: + if (c == ']') + state = 4; + *s++ = c; + continue; + case 2: + if (c == '-') + state = 6; + *s++ = c; + continue; + case 3: + if (c == '?') + state = 8; + *s++ = c; + continue; + /* CDATA */ + case 4: + if (c == ']') + state = 5; + else + state = 1; + *s++ = c; + continue; + case 5: + if (c == '>') + state = 0; + else + state = 1; + *s++ = c; + continue; + /* comment */ + case 6: + if (c == '-') + state = 7; + else + state = 2; + *s++ = c; + continue; + case 7: + if (c == '>') + state = 0; + else + state = 2; + *s++ = c; + continue; + /* PI */ + case 8: + if (c == '>') + state = 0; + else + state = 3; + *s++ = c; + continue; + } + switch (c) + { + case '/': + if (n > 0) + { c = soap_getchar(soap); + if (c == '>') + n--; + soap_unget(soap, c); + } + *s++ = '/'; + break; + case '<': + c = soap_getchar(soap); + if (c == '/') + { if (n == 0) + { c = SOAP_TT; + goto end; + } + n--; + } + else if (c == '!') + { c = soap_getchar(soap); + if (c == '[') + { do c = soap_getchar(soap); + while ((int)c != EOF && c != '['); + if ((int)c == EOF) + goto end; + t = (char*)"![CDATA["; + m = 8; + state = 1; + } + else if (c == '-') + { if ((c = soap_getchar(soap)) == '-') + state = 2; + t = (char*)"!-"; + m = 2; + soap_unget(soap, c); + } + else + { t = (char*)"!"; + m = 1; + soap_unget(soap, c); + } + *s++ = '<'; + break; + } + else if (c == '?') + state = 3; + else + n++; + soap_unget(soap, c); + *s++ = '<'; + break; + case '>': + *s++ = '>'; + break; + case '"': + *s++ = '"'; + break; + default: +#ifndef WITH_LEANER +#ifdef HAVE_WCTOMB + if (soap->mode & SOAP_C_MBSTRING) + { m = wctomb(buf, c & 0x7FFFFFFF); + if (m >= 1 && m <= (int)MB_CUR_MAX) + { t = buf; + *s++ = *t++; + m--; + } + else + { *s++ = SOAP_UNKNOWN_CHAR; + m = 0; + } + } + else +#endif +#endif + *s++ = (char)(c & 0xFF); + } + l++; + if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); + soap->error = SOAP_LENGTH; + return NULL; + } + } + } + } +#endif +#ifdef WITH_FAST + soap->labidx = 0; /* use look-aside buffer */ +#else + if (soap_new_block(soap)) + return NULL; +#endif + for (;;) + { +#ifdef WITH_FAST + register size_t k; + if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */ + return NULL; + s = soap->labbuf + soap->labidx; /* space to populate */ + k = soap->lablen - soap->labidx; /* number of bytes available */ + soap->labidx = soap->lablen; /* claim this space */ +#else + register size_t k = SOAP_BLKLEN; + if (!(s = (char*)soap_push_block(soap, k))) + return NULL; +#endif + for (i = 0; i < k; i++) + { if (m > 0) + { *s++ = *t++; /* copy multibyte characters */ + m--; + continue; + } + if (soap->mode & SOAP_C_UTFSTRING) + { if (((c = soap_get(soap)) & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP) + { c &= 0x7FFFFFFF; + t = buf; + if (c < 0x0800) + *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); + else + { if (c < 0x010000) + *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + else + { if (c < 0x200000) + *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + else + { if (c < 0x04000000) + *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + else + { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + } + *t++ = (char)(0x80 | (c & 0x3F)); + m = (int)(t - buf) - 1; + t = buf; + *s++ = *t++; + continue; + } + } + else + c = soap_getutf8(soap); + switch (c) + { + case SOAP_TT: + if (n == 0) + goto end; + n--; + *s++ = '<'; + t = (char*)"/"; + m = 1; + break; + case SOAP_LT: + n++; + *s++ = '<'; + break; + case SOAP_GT: + *s++ = '>'; + break; + case SOAP_QT: + *s++ = '"'; + break; + case SOAP_AP: + *s++ = '\''; + break; + case '/': + if (n > 0) + { c = soap_get(soap); + if (c == SOAP_GT) + n--; + soap_unget(soap, c); + } + *s++ = '/'; + break; + case '<' | 0x80000000: + if (flag) + *s++ = '<'; + else + { *s++ = '&'; + t = (char*)"lt;"; + m = 3; + } + break; + case '>' | 0x80000000: + if (flag) + *s++ = '>'; + else + { *s++ = '&'; + t = (char*)"gt;"; + m = 3; + } + break; + case '&' | 0x80000000: + if (flag) + *s++ = '&'; + else + { *s++ = '&'; + t = (char*)"amp;"; + m = 4; + } + break; + case '"' | 0x80000000: + if (flag) + *s++ = '"'; + else + { *s++ = '&'; + t = (char*)"quot;"; + m = 5; + } + break; + case '\'' | 0x80000000: + if (flag) + *s++ = '\''; + else + { *s++ = '&'; + t = (char*)"apos;"; + m = 5; + } + break; + default: + if ((int)c == EOF) + goto end; +#ifndef WITH_LEANER +#ifdef HAVE_WCTOMB + if (soap->mode & SOAP_C_MBSTRING) + { m = wctomb(buf, c & 0x7FFFFFFF); + if (m >= 1 && m <= (int)MB_CUR_MAX) + { t = buf; + *s++ = *t++; + m--; + } + else + { *s++ = SOAP_UNKNOWN_CHAR; + m = 0; + } + } + else +#endif +#endif + *s++ = (char)(c & 0xFF); + } + l++; + if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); + soap->error = SOAP_LENGTH; + return NULL; + } + } + } +end: + soap_unget(soap, c); + *s = '\0'; +#ifdef WITH_FAST + t = soap_strdup(soap, soap->labbuf); +#else + soap_size_block(soap, i+1); + t = soap_save_block(soap, NULL, 0); +#endif + if ((soap->mode & SOAP_XML_STRICT) && l < minlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen)); + soap->error = SOAP_LENGTH; + return NULL; + } +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { if (flag == 3) + soap->dom->tail = t; + else + soap->dom->data = t; + } +#endif + if (flag == 2) + if (soap_s2QName(soap, t, &t)) + return NULL; + return t; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_wstring_out(struct soap *soap, const wchar_t *s, int flag) +{ const char *t; + char tmp; + register soap_wchar c; +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { wchar_t *r = (wchar_t*)s; + int n = 1; + while (*r++) + n++; + soap->dom->wide = r = (wchar_t*)soap_malloc(soap, n * sizeof(wchar_t)); + while (n--) + *r++ = *s++; + return SOAP_OK; + } +#endif + while ((c = *s++)) + { switch (c) + { + case 0x09: + if (flag) + t = " "; + else + t = "\t"; + break; + case 0x0A: + if (flag || !(soap->mode & SOAP_XML_CANONICAL)) + t = " "; + else + t = "\n"; + break; + case 0x0D: + t = " "; + break; + case '&': + t = "&"; + break; + case '<': + t = "<"; + break; + case '>': + if (flag) + t = ">"; + else + t = ">"; + break; + case '"': + if (flag) + t = """; + else + t = "\""; + break; + default: + if (c >= 0x20 && c < 0x80) + { tmp = (char)c; + if (soap_send_raw(soap, &tmp, 1)) + return soap->error; + } + else if (soap_pututf8(soap, (unsigned long)c)) + return soap->error; + continue; + } + if (soap_send(soap, t)) + return soap->error; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +wchar_t * +SOAP_FMAC2 +soap_wstring_in(struct soap *soap, int flag, long minlen, long maxlen) +{ wchar_t *s; + register int i, n = 0; + register long l = 0; + register soap_wchar c; + const char *t = NULL; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading wide string content\n")); + if (soap->peeked) + { if (!soap->body) + return NULL; + if (*soap->tag) + { n = 1; + soap->peeked = 0; + } + } + if (soap_new_block(soap)) + return NULL; + for (;;) + { if (!(s = (wchar_t*)soap_push_block(soap, sizeof(wchar_t)*SOAP_BLKLEN))) + return NULL; + for (i = 0; i < SOAP_BLKLEN; i++) + { if (t) + { *s++ = (wchar_t)*t++; + if (!*t) + t = NULL; + continue; + } + c = soap_getutf8(soap); + switch (c) + { + case SOAP_TT: + if (n == 0) + goto end; + n--; + *s++ = '<'; + soap_unget(soap, '/'); + break; + case SOAP_LT: + n++; + *s++ = '<'; + break; + case SOAP_GT: + *s++ = '>'; + break; + case SOAP_QT: + *s++ = '"'; + break; + case SOAP_AP: + *s++ = '\''; + break; + case '/': + if (n > 0) + { c = soap_getutf8(soap); + if (c == SOAP_GT) + n--; + soap_unget(soap, c); + } + *s++ = '/'; + break; + case '<': + if (flag) + *s++ = (soap_wchar)'<'; + else + { *s++ = (soap_wchar)'&'; + t = "lt;"; + } + break; + case '>': + if (flag) + *s++ = (soap_wchar)'>'; + else + { *s++ = (soap_wchar)'&'; + t = "gt;"; + } + break; + case '"': + if (flag) + *s++ = (soap_wchar)'"'; + else + { *s++ = (soap_wchar)'&'; + t = "quot;"; + } + break; + default: + if ((int)c == EOF) + goto end; + *s++ = (wchar_t)c & 0x7FFFFFFF; + } + l++; + if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); + soap->error = SOAP_LENGTH; + return NULL; + } + } + } +end: + soap_unget(soap, c); + *s = '\0'; + soap_size_block(soap, sizeof(wchar_t) * (i + 1)); + if ((soap->mode & SOAP_XML_STRICT) && l < minlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen)); + soap->error = SOAP_LENGTH; + return NULL; + } + s = (wchar_t*)soap_save_block(soap, NULL, 0); +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + soap->dom->wide = s; +#endif + return s; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_int2s(struct soap *soap, int n) +{ return soap_long2s(soap, (long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outint(struct soap *soap, const char *tag, int id, const int *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_long2s(soap, (long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2int(struct soap *soap, const char *s, int *p) +{ if (s) + { char *r; +#ifndef WITH_NOIO +#ifndef WITH_LEAN + soap_reset_errno; +#endif +#endif + *p = (int)soap_strtol(s, &r, 10); + if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r +#ifndef WITH_NOIO +#ifndef WITH_LEAN + || soap_errno == SOAP_ERANGE +#endif +#endif + ) + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int * +SOAP_FMAC2 +soap_inint(struct soap *soap, const char *tag, int *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":int") + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (int*)soap_id_enter(soap, soap->id, p, t, sizeof(int), 0, NULL, NULL, NULL); + if (*soap->href) + p = (int*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(int), 0, NULL); + else if (p) + { if (soap_s2int(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_long2s(struct soap *soap, long n) +{ sprintf(soap->tmpbuf, "%ld", n); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outlong(struct soap *soap, const char *tag, int id, const long *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_long2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2long(struct soap *soap, const char *s, long *p) +{ if (s) + { char *r; +#ifndef WITH_NOIO +#ifndef WITH_LEAN + soap_reset_errno; +#endif +#endif + *p = soap_strtol(s, &r, 10); + if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r +#ifndef WITH_NOIO +#ifndef WITH_LEAN + || soap_errno == SOAP_ERANGE +#endif +#endif + ) + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +long * +SOAP_FMAC2 +soap_inlong(struct soap *soap, const char *tag, long *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":int") + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (long*)soap_id_enter(soap, soap->id, p, t, sizeof(long), 0, NULL, NULL, NULL); + if (*soap->href) + p = (long*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(long), 0, NULL); + else if (p) + { if (soap_s2long(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_LONG642s(struct soap *soap, LONG64 n) +{ sprintf(soap->tmpbuf, SOAP_LONG_FORMAT, n); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outLONG64(struct soap *soap, const char *tag, int id, const LONG64 *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_LONG642s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2LONG64(struct soap *soap, const char *s, LONG64 *p) +{ if (s) + { +#ifdef HAVE_STRTOLL + char *r; +#ifndef WITH_NOIO +#ifndef WITH_LEAN + soap_reset_errno; +#endif +#endif + *p = strtoll(s, &r, 10); + if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r +#ifndef WITH_NOIO +#ifndef WITH_LEAN + || soap_errno == SOAP_ERANGE +#endif +#endif + ) +#else +# ifdef HAVE_SSCANF + if (sscanf(s, SOAP_LONG_FORMAT, p) != 1) +# endif +#endif + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +LONG64 * +SOAP_FMAC2 +soap_inLONG64(struct soap *soap, const char *tag, LONG64 *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":integer") + && soap_match_tag(soap, soap->type, ":positiveInteger") + && soap_match_tag(soap, soap->type, ":negativeInteger") + && soap_match_tag(soap, soap->type, ":nonPositiveInteger") + && soap_match_tag(soap, soap->type, ":nonNegativeInteger") + && soap_match_tag(soap, soap->type, ":long") + && soap_match_tag(soap, soap->type, ":int") + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (LONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(LONG64), 0, NULL, NULL, NULL); + if (*soap->href) + p = (LONG64*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(LONG64), 0, NULL); + else if (p) + { if (soap_s2LONG64(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_byte2s(struct soap *soap, char n) +{ return soap_long2s(soap, (long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outbyte(struct soap *soap, const char *tag, int id, const char *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_long2s(soap, (long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2byte(struct soap *soap, const char *s, char *p) +{ if (s) + { long n; + char *r; + n = soap_strtol(s, &r, 10); + if (s == r || *r || n < -128 || n > 127) + soap->error = SOAP_TYPE; + *p = (char)n; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_inbyte(struct soap *soap, const char *tag, char *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (char*)soap_id_enter(soap, soap->id, p, t, sizeof(char), 0, NULL, NULL, NULL); + if (*soap->href) + p = (char*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(char), 0, NULL); + else if (p) + { if (soap_s2byte(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_short2s(struct soap *soap, short n) +{ return soap_long2s(soap, (long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outshort(struct soap *soap, const char *tag, int id, const short *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_long2s(soap, (long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2short(struct soap *soap, const char *s, short *p) +{ if (s) + { long n; + char *r; + n = soap_strtol(s, &r, 10); + if (s == r || *r || n < -32768 || n > 32767) + soap->error = SOAP_TYPE; + *p = (short)n; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +short * +SOAP_FMAC2 +soap_inshort(struct soap *soap, const char *tag, short *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (short*)soap_id_enter(soap, soap->id, p, t, sizeof(short), 0, NULL, NULL, NULL); + if (*soap->href) + p = (short*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(short), 0, NULL); + else if (p) + { if (soap_s2short(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_float2s(struct soap *soap, float n) +{ char *s; + if (soap_isnan((double)n)) + s = "NaN"; + else if (soap_ispinff(n)) + s = "INF"; + else if (soap_isninff(n)) + s = "-INF"; + else + { char *t; + s = soap->tmpbuf; + sprintf(soap->tmpbuf, soap->float_format, n); + t = strchr(s, ','); /* convert decimal comma to DP */ + if (t) + *t = '.'; + } + return s; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outfloat(struct soap *soap, const char *tag, int id, const float *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_float2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2float(struct soap *soap, const char *s, float *p) +{ if (s) + { if (!*s) + return soap->error = SOAP_TYPE; + if (!soap_tag_cmp(s, "INF")) + *p = FLT_PINFTY; + else if (!soap_tag_cmp(s, "+INF")) + *p = FLT_PINFTY; + else if (!soap_tag_cmp(s, "-INF")) + *p = FLT_NINFTY; + else if (!soap_tag_cmp(s, "NaN")) + *p = FLT_NAN; + else + { +/* On some systems, strtof appears to be broken or doesn't link: use with caution */ +#if defined(HAVE_STRTOF) + char *r; + *p = strtof((char*)s, &r); + if (*r) +#elif defined(HAVE_STRTOD) + char *r; + *p = (float)strtod(s, &r); + if (*r) +#endif +#ifdef HAVE_SSCANF + if (sscanf(s, "%g", p) != 1) + soap->error = SOAP_TYPE; +#else + soap->error = SOAP_TYPE; +#endif + } + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static int soap_isnumeric(struct soap *soap, const char *type) +{ if (soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":float") + && soap_match_tag(soap, soap->type, ":double") + && soap_match_tag(soap, soap->type, ":decimal") + && soap_match_tag(soap, soap->type, ":integer") + && soap_match_tag(soap, soap->type, ":positiveInteger") + && soap_match_tag(soap, soap->type, ":negativeInteger") + && soap_match_tag(soap, soap->type, ":nonPositiveInteger") + && soap_match_tag(soap, soap->type, ":nonNegativeInteger") + && soap_match_tag(soap, soap->type, ":long") + && soap_match_tag(soap, soap->type, ":int") + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte") + && soap_match_tag(soap, soap->type, ":unsignedLong") + && soap_match_tag(soap, soap->type, ":unsignedInt") + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return SOAP_ERR; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +float * +SOAP_FMAC2 +soap_infloat(struct soap *soap, const char *tag, float *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type != '\0' && soap_isnumeric(soap, type)) + return NULL; +#endif + p = (float*)soap_id_enter(soap, soap->id, p, t, sizeof(float), 0, NULL, NULL, NULL); + if (*soap->href) + p = (float*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(float), 0, NULL); + else if (p) + { if (soap_s2float(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_double2s(struct soap *soap, double n) +{ char *s; + if (soap_isnan(n)) + s = "NaN"; + else if (soap_ispinfd(n)) + s = "INF"; + else if (soap_isninfd(n)) + s = "-INF"; + else + { char *t; + s = soap->tmpbuf; + sprintf(soap->tmpbuf, soap->double_format, n); + t = strchr(s, ','); /* convert decimal comma to DP */ + if (t) + *t = '.'; + } + return s; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outdouble(struct soap *soap, const char *tag, int id, const double *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_double2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2double(struct soap *soap, const char *s, double *p) +{ if (s) + { if (!*s) + return soap->error = SOAP_TYPE; + if (!soap_tag_cmp(s, "INF")) + *p = DBL_PINFTY; + else if (!soap_tag_cmp(s, "+INF")) + *p = DBL_PINFTY; + else if (!soap_tag_cmp(s, "-INF")) + *p = DBL_NINFTY; + else if (!soap_tag_cmp(s, "NaN")) + *p = DBL_NAN; + else + { +#ifdef HAVE_STRTOD + char *r; + *p = strtod(s, &r); + if (*r) +#endif +#ifdef HAVE_SSCANF + if (sscanf(s, "%lg", p) != 1) + soap->error = SOAP_TYPE; +#else + soap->error = SOAP_TYPE; +#endif + } + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +double * +SOAP_FMAC2 +soap_indouble(struct soap *soap, const char *tag, double *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type != '\0' && soap_isnumeric(soap, type)) + return NULL; +#endif + p = (double*)soap_id_enter(soap, soap->id, p, t, sizeof(double), 0, NULL, NULL, NULL); + if (*soap->href) + p = (double*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(double), 0, NULL); + else if (p) + { if (soap_s2double(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_unsignedByte2s(struct soap *soap, unsigned char n) +{ return soap_unsignedLong2s(soap, (unsigned long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outunsignedByte(struct soap *soap, const char *tag, int id, const unsigned char *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2unsignedByte(struct soap *soap, const char *s, unsigned char *p) +{ if (s) + { unsigned long n; + char *r; + n = soap_strtoul(s, &r, 10); + if (s == r || *r || n > 255) + soap->error = SOAP_TYPE; + *p = (unsigned char)n; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +unsigned char * +SOAP_FMAC2 +soap_inunsignedByte(struct soap *soap, const char *tag, unsigned char *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (unsigned char*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned char), 0, NULL, NULL, NULL); + if (*soap->href) + p = (unsigned char*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned char), 0, NULL); + else if (p) + { if (soap_s2unsignedByte(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_unsignedShort2s(struct soap *soap, unsigned short n) +{ return soap_unsignedLong2s(soap, (unsigned long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outunsignedShort(struct soap *soap, const char *tag, int id, const unsigned short *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2unsignedShort(struct soap *soap, const char *s, unsigned short *p) +{ if (s) + { unsigned long n; + char *r; + n = soap_strtoul(s, &r, 10); + if (s == r || *r || n > 65535) + soap->error = SOAP_TYPE; + *p = (unsigned short)n; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +unsigned short * +SOAP_FMAC2 +soap_inunsignedShort(struct soap *soap, const char *tag, unsigned short *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (unsigned short*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned short), 0, NULL, NULL, NULL); + if (*soap->href) + p = (unsigned short*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned short), 0, NULL); + else if (p) + { if (soap_s2unsignedShort(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_unsignedInt2s(struct soap *soap, unsigned int n) +{ return soap_unsignedLong2s(soap, (unsigned long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outunsignedInt(struct soap *soap, const char *tag, int id, const unsigned int *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2unsignedInt(struct soap *soap, const char *s, unsigned int *p) +{ if (s) + { char *r; +#ifndef WITH_NOIO +#ifndef WITH_LEAN + soap_reset_errno; +#endif +#endif + *p = (unsigned int)soap_strtoul(s, &r, 10); + if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r +#ifndef WITH_NOIO +#ifndef WITH_LEAN + || soap_errno == SOAP_ERANGE +#endif +#endif + ) + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +unsigned int * +SOAP_FMAC2 +soap_inunsignedInt(struct soap *soap, const char *tag, unsigned int *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":unsignedInt") + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (unsigned int*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned int), 0, NULL, NULL, NULL); + if (*soap->href) + p = (unsigned int*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned int), 0, NULL); + else if (p) + { if (soap_s2unsignedInt(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_unsignedLong2s(struct soap *soap, unsigned long n) +{ sprintf(soap->tmpbuf, "%lu", n); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outunsignedLong(struct soap *soap, const char *tag, int id, const unsigned long *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_unsignedLong2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2unsignedLong(struct soap *soap, const char *s, unsigned long *p) +{ if (s) + { char *r; +#ifndef WITH_NOIO +#ifndef WITH_LEAN + soap_reset_errno; +#endif +#endif + *p = soap_strtoul(s, &r, 10); + if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r +#ifndef WITH_NOIO +#ifndef WITH_LEAN + || soap_errno == SOAP_ERANGE +#endif +#endif + ) + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +unsigned long * +SOAP_FMAC2 +soap_inunsignedLong(struct soap *soap, const char *tag, unsigned long *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":unsignedInt") + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (unsigned long*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned long), 0, NULL, NULL, NULL); + if (*soap->href) + p = (unsigned long*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned long), 0, NULL); + else if (p) + { if (soap_s2unsignedLong(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_ULONG642s(struct soap *soap, ULONG64 n) +{ sprintf(soap->tmpbuf, SOAP_ULONG_FORMAT, n); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outULONG64(struct soap *soap, const char *tag, int id, const ULONG64 *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_ULONG642s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2ULONG64(struct soap *soap, const char *s, ULONG64 *p) +{ if (s) + { +#ifdef HAVE_STRTOULL + char *r; +#ifndef WITH_NOIO +#ifndef WITH_LEAN + soap_reset_errno; +#endif +#endif + *p = strtoull(s, &r, 10); + if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r +#ifndef WITH_NOIO +#ifndef WITH_LEAN + || soap_errno == SOAP_ERANGE +#endif +#endif + ) +#else +# ifdef HAVE_SSCANF + if (sscanf(s, SOAP_ULONG_FORMAT, p) != 1) +# endif +#endif + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +ULONG64 * +SOAP_FMAC2 +soap_inULONG64(struct soap *soap, const char *tag, ULONG64 *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":positiveInteger") + && soap_match_tag(soap, soap->type, ":nonNegativeInteger") + && soap_match_tag(soap, soap->type, ":unsignedLong") + && soap_match_tag(soap, soap->type, ":unsignedInt") + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } + p = (ULONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(ULONG64), 0, NULL, NULL, NULL); + if (*soap->href) + p = (ULONG64*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(ULONG64), 0, NULL); + else if (p) + { if (soap_s2ULONG64(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2string(struct soap *soap, const char *s, char **t) +{ *t = NULL; + if (s) + { if (!(*t = soap_strdup(soap, s))) + return soap->error = SOAP_EOM; + if (!(soap->mode & (SOAP_ENC_LATIN | SOAP_C_UTFSTRING))) + { /* TODO: consider truncating UTF8 to ASCII for regular XML attribute strings? */ + } + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2QName(struct soap *soap, const char *s, char **t) +{ if (s) + { struct soap_nlist *np = soap->nlist; + const char *p; + /* if there is no namespace stack, or prefix is "xml" then pass string */ + if (!np || !strncmp(s, "xml:", 4)) + { *t = soap_strdup(soap, s); + return SOAP_OK; + } + /* else we normalize the QName by replacing its prefix */ + p = strchr(s, ':'); + if (p) + { register int n = p - s; + while (np && (strncmp(np->id, s, n) || np->id[n])) + np = np->next; + p++; + } + else + { while (np && *np->id) + np = np->next; + p = s; + } + if (np) + { if (np->index >= 0 && soap->local_namespaces) + { register const char *q = soap->local_namespaces[np->index].id; + if (q) + { if ((*t = (char*)soap_malloc(soap, strlen(p) + strlen(q) + 2))) + sprintf(*t, "%s:%s", q, p); + return SOAP_OK; + } + } + if (np->ns) + { if ((*t = (char*)soap_malloc(soap, strlen(p) + strlen(np->ns) + 4))) + sprintf(*t, "\"%s\":%s", np->ns, p); + return SOAP_OK; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Namespace prefix of '%s' not defined (index=%d, URI=%s)\n", s, np->index, np->ns?np->ns:"")); + return soap->error = SOAP_NAMESPACE; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Namespace prefix of '%s' not defined, assuming empty namespace\n", s)); + if ((*t = (char*)soap_malloc(soap, strlen(p) + 4))) + sprintf(*t, "\"\":%s", p); + } + else + *t = NULL; + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_QName2s(struct soap *soap, const char *s) +{ struct Namespace *p; + char *t; + int n; + if (!s || *s != '"') + { +#ifndef WITH_LEAN + if (s && (soap->mode & SOAP_XML_CANONICAL)) + { t = (char*)strchr(s, ':'); + if (t) + soap_utilize_ns(soap, s, t - s); + } +#endif + return s; + } + s++; + if ((p = soap->local_namespaces)) + { for (; p->id; p++) + { if (p->ns) + if (!soap_tag_cmp(s, p->ns)) + break; + if (p->in) + if (!soap_tag_cmp(s, p->in)) + break; + } + if (p && p->id) + { s = strchr(s, '"'); + if (s) + { t = (char*)soap_malloc(soap, strlen(p->id) + strlen(s)); + strcpy(t, p->id); + strcat(t, s + 1); + return t; + } + } + } + t = (char*)strchr(s, '"'); + if (t) + n = t - s; + else + n = 0; + t = soap_strdup(soap, s); + t[n] = '\0'; + sprintf(soap->tmpbuf, "xmlns:_%d", soap->idnum++); + soap_set_attr(soap, soap->tmpbuf, t); + s = strchr(s, '"'); + if (s) + { t = (char*)soap_malloc(soap, strlen(soap->tmpbuf) + strlen(s) - 6); + strcpy(t, soap->tmpbuf + 6); + strcat(t, s + 1); + } + return t; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2wchar(struct soap *soap, const char *s, wchar_t **t) +{ wchar_t *r; + if (!s) + *t = NULL; + else + { *t = r = (wchar_t*)soap_malloc(soap, sizeof(wchar_t) * (strlen(s) + 1)); + if (!r) + return soap->error; + if (soap->mode & SOAP_ENC_LATIN) + { while (*s) + *r++ = (wchar_t)*s++; + } + else + { /* Convert UTF8 to wchar */ + while (*s) + { register soap_wchar c, c1, c2, c3, c4; + c = *s++; + if (c < 0x80) + *r++ = (wchar_t)c; + else + { c1 = (soap_wchar)*s++ & 0x3F; + if (c < 0xE0) + *r++ = (wchar_t)(((soap_wchar)(c & 0x1F) << 6) | c1); + else + { c2 = (soap_wchar)*s++ & 0x3F; + if (c < 0xF0) + *r++ = (wchar_t)(((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2); + else + { c3 = (soap_wchar)*s++ & 0x3F; + if (c < 0xF8) + *r++ = (wchar_t)(((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3); + else + { c4 = (soap_wchar)*s++ & 0x3F; + if (c < 0xFC) + *r++ = (wchar_t)(((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4); + else + *r++ = (wchar_t)(((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(*s++ & 0x3F)); + } + } + } + } + } + } + *r = L'\0'; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_wchar2s(struct soap *soap, const wchar_t *s) +{ register soap_wchar c; + register char *r, *t; + const wchar_t *q = s; + size_t n = 0; + while ((c = *q++)) + { if (c > 0 && c < 0x80) + n++; + else + n += 6; + } + r = t = (char*)soap_malloc(soap, n + 1); + if (r) + { /* Convert wchar to UTF8 */ + while ((c = *s++)) + { if (c > 0 && c < 0x80) + *t++ = (char)c; + else + { if (c < 0x0800) + *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); + else + { if (c < 0x010000) + *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + else + { if (c < 0x200000) + *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + else + { if (c < 0x04000000) + *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + else + { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + } + *t++ = (char)(0x80 | (c & 0x3F)); + } + } + *t = '\0'; + } + return r; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outstring(struct soap *soap, const char *tag, int id, char *const*p, const char *type, int n) +{ id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n); + if (id < 0) + return soap->error; + if (!**p && (soap->mode & SOAP_C_NILSTRING)) + return soap_element_null(soap, tag, id, type); + if (soap_element_begin_out(soap, tag, id, type) + || soap_string_out(soap, *p, 0) + || soap_element_end_out(soap, tag)) + return soap->error; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char ** +SOAP_FMAC2 +soap_instring(struct soap *soap, const char *tag, char **p, const char *type, int t, int flag, long minlen, long maxlen) +{ if (soap_element_begin_in(soap, tag, 1, NULL)) + { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG) + return NULL; + soap->error = SOAP_OK; + } + if (!p) + if (!(p = (char**)soap_malloc(soap, sizeof(char*)))) + return NULL; + if (soap->body) + { *p = soap_string_in(soap, flag, minlen, maxlen); + if (!*p || !(char*)soap_id_enter(soap, soap->id, *p, t, sizeof(char*), 0, NULL, NULL, NULL)) + return NULL; + } + else if (soap->null) + *p = NULL; + else + *p = (char*)SOAP_STR_EOS; + if (*soap->href) + p = (char**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(char**), 0); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outwstring(struct soap *soap, const char *tag, int id, wchar_t *const*p, const char *type, int n) +{ id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n); + if (id < 0) + return soap->error; + if (!**p && (soap->mode & SOAP_C_NILSTRING)) + return soap_element_null(soap, tag, id, type); + if (soap_element_begin_out(soap, tag, id, type) + || soap_wstring_out(soap, *p, 0) + || soap_element_end_out(soap, tag)) + return soap->error; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +wchar_t ** +SOAP_FMAC2 +soap_inwstring(struct soap *soap, const char *tag, wchar_t **p, const char *type, int t, long minlen, long maxlen) +{ if (soap_element_begin_in(soap, tag, 1, NULL)) + { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG) + return NULL; + soap->error = SOAP_OK; + } + if (!p) + if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*)))) + return NULL; + if (soap->body) + { *p = soap_wstring_in(soap, 1, minlen, maxlen); + if (!*p || !(wchar_t*)soap_id_enter(soap, soap->id, *p, t, sizeof(wchar_t*), 0, NULL, NULL, NULL)) + return NULL; + } + else if (soap->null) + *p = NULL; + else + *p = (wchar_t*)SOAP_STR_EOS; + if (*soap->href) + p = (wchar_t**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(wchar_t**), 0); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static time_t +soap_timegm(struct tm *T) +{ +#if defined(HAVE_TIMEGM) + return timegm(T); +#else + time_t t, g, z; +#ifdef HAVE_GMTIME_R + struct tm tm, *tmp = &tm; +#else + struct tm *tmp; +#endif + t = mktime(T); + if (t == -1) + return -1; +#ifdef HAVE_GMTIME_R + gmtime_r(&t, tmp); +#else + tmp = gmtime(&t); +#endif + tmp->tm_isdst = 0; + g = mktime(tmp); + if (g == -1) + return -1; + z = g - t; + return t - z; +#endif +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_dateTime2s(struct soap *soap, time_t n) +{ struct tm T, *pT = &T; +#if defined(HAVE_GMTIME_R) + if (gmtime_r(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); + /* The following defines were added for VxWorks*/ +#elif defined(HAVE_PGMTIME_R) + if (gmtime_r(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); +#elif defined(HAVE_PGMTIME) + if (gmtime(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); +#elif defined(HAVE_GMTIME) + if ((pT = gmtime(&n))) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); +#elif defined(HAVE_GETTIMEOFDAY) + struct timezone tz; + memset((void*)&tz, 0, sizeof(tz)); +# if defined(HAVE_LOCALTIME_R) + if (localtime_r(&n, pT)) + { struct timeval tv; + gettimeofday(&tv, &tz); + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60); + } +# else + if ((pT = localtime(&n))) + { struct timeval tv; + gettimeofday(&tv, &tz); + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60); + } +#endif +#elif defined(HAVE_FTIME) + struct timeb t; + memset((void*)&t, 0, sizeof(t)); +# if defined(HAVE_LOCALTIME_R) + if (localtime_r(&n, pT)) + { +#ifdef __BORLANDC__ + ::ftime(&t); +#else + ftime(&t); +#endif + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60); + } + /* The following defines were added for VxWorks*/ +# elif defined(HAVE_PLOCALTIME_R) + if (localtime_r(&n, pT)) + { strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf+strlen(soap->tmpbuf), "%+03d:%02d", t.timezone/60, abs(t.timezone)%60); + } +# else + if ((pT = localtime(&n))) + { +#ifdef __BORLANDC__ + ::ftime(&t); +#else + ftime(&t); +#endif + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60); + } +# endif +#elif defined(HAVE_LOCALTIME_R) + if (localtime_r(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + /* The following defines were added for VxWorks*/ +#elif defined(HAVE_PLOCALTIME_R) + if (localtime_r(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); +#else + if ((pT = localtime(&n))) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); +#endif + else + strcpy(soap->tmpbuf, "1969-12-31T23:59:59Z"); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outdateTime(struct soap *soap, const char *tag, int id, const time_t *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_dateTime2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2dateTime(struct soap *soap, const char *s, time_t *p) +{ if (s) + { struct tm T; + char zone[32]; + const char *t; + memset((void*)&T, 0, sizeof(T)); + zone[sizeof(zone)-1] = '\0'; + if (strchr(s, '-')) + t = "%d-%d-%dT%d:%d:%d%31s"; + else if (strchr(s, ':')) + t = "%4d%2d%2dT%d:%d:%d%31s"; + else /* parse non-XSD-standard alternative ISO 8601 format */ + t = "%4d%2d%2dT%2d%2d%2d%31s"; + sscanf(s, t, &T.tm_year, &T.tm_mon, &T.tm_mday, &T.tm_hour, &T.tm_min, &T.tm_sec, zone); + if (T.tm_year == 1) + T.tm_year = 70; + else + T.tm_year -= 1900; + T.tm_mon--; + if (*zone) + { if (*zone == '.') + { for (s = zone + 1; *s; s++) + if (*s < '0' || *s > '9') + break; + } + else + s = zone; + if (*s == '+' || *s == '-') + { int h = 0, m = 0; + if (s[3] == ':') + { sscanf(s, "%d:%d", &h, &m); + if (h < 0) + m = -m; + } + else + { m = (int)atol(s); + h = m / 100; + m = m % 100; + } + T.tm_hour -= h; + T.tm_min -= m; + } + T.tm_isdst = 0; + *p = soap_timegm(&T); + } + else + { T.tm_isdst = -1; + *p = mktime(&T); /* no time zone: suppose it is localtime? */ + } + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +time_t * +SOAP_FMAC2 +soap_indateTime(struct soap *soap, const char *tag, time_t *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":dateTime")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } + p = (time_t*)soap_id_enter(soap, soap->id, p, t, sizeof(time_t), 0, NULL, NULL, NULL); + if (*soap->href) + p = (time_t*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(time_t), 0, NULL); + else if (p) + { if (soap_s2dateTime(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outliteral(struct soap *soap, const char *tag, char *const*p, const char *type) +{ int i; + const char *t = NULL; + if (tag && *tag != '-') + { if (soap->local_namespaces && (t = strchr(tag, ':'))) + { strncpy(soap->tmpbuf, tag, t-tag); + soap->tmpbuf[t-tag] = '\0'; + for (i = 0; soap->local_namespaces[i].id; i++) + if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id)) + break; + t++; + if (soap_element(soap, t, 0, type) + || soap_attribute(soap, "xmlns", soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS) + || soap_element_start_end_out(soap, NULL)) + return soap->error; + } + else + { t = tag; + if (soap_element_begin_out(soap, t, 0, type)) + return soap->error; + } + } + if (p && *p) + { if (soap_send(soap, *p)) + return soap->error; + } + if (t) + return soap_element_end_out(soap, t); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char ** +SOAP_FMAC2 +soap_inliteral(struct soap *soap, const char *tag, char **p) +{ if (soap_element_begin_in(soap, tag, 1, NULL)) + { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT) + return NULL; + soap->error = SOAP_OK; + } + if (!p) + if (!(p = (char**)soap_malloc(soap, sizeof(char*)))) + return NULL; + if (soap->body) + *p = soap_string_in(soap, 0, -1, -1); + else if (soap->null) + *p = NULL; + else + *p = (char*)SOAP_STR_EOS; + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outwliteral(struct soap *soap, const char *tag, wchar_t *const*p, const char *type) +{ int i; + const char *t = NULL; + if (tag && *tag != '-') + { if (soap->local_namespaces && (t = strchr(tag, ':'))) + { strncpy(soap->tmpbuf, tag, t-tag); + soap->tmpbuf[t-tag] = '\0'; + for (i = 0; soap->local_namespaces[i].id; i++) + if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id)) + break; + t++; + if (soap_element(soap, t, 0, type) + || soap_attribute(soap, "xmlns", soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS) + || soap_element_start_end_out(soap, NULL)) + return soap->error; + } + else + { t = tag; + if (soap_element_begin_out(soap, t, 0, type)) + return soap->error; + } + if (soap_send(soap, soap->tmpbuf)) + return soap->error; + } + if (p) + { wchar_t c; + const wchar_t *s = *p; + while ((c = *s++)) + { if (soap_pututf8(soap, (unsigned long)c)) + return soap->error; + } + } + if (t) + return soap_element_end_out(soap, t); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +wchar_t ** +SOAP_FMAC2 +soap_inwliteral(struct soap *soap, const char *tag, wchar_t **p) +{ if (soap_element_begin_in(soap, tag, 1, NULL)) + { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT) + return NULL; + soap->error = SOAP_OK; + } + if (!p) + if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*)))) + return NULL; + if (soap->body) + *p = soap_wstring_in(soap, 0, -1, -1); + else if (soap->null) + *p = NULL; + else + *p = (wchar_t*)SOAP_STR_EOS; + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char * +SOAP_FMAC2 +soap_value(struct soap *soap) +{ register size_t i; + register soap_wchar c = 0; + register char *s = soap->tmpbuf; + if (!soap->body) + return SOAP_STR_EOS; + do c = soap_get(soap); + while (soap_blank(c)); + for (i = 0; i < sizeof(soap->tmpbuf) - 1; i++) + { if (c == SOAP_TT || (int)c == EOF) + break; + *s++ = (char)c; + c = soap_get(soap); + } + for (s--; i > 0; i--, s--) + { if (!soap_blank(*s)) + break; + } + s[1] = '\0'; + if ((int)c == EOF || c == SOAP_TT) + soap_unget(soap, c); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element content value='%s'\n", soap->tmpbuf)); +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + soap->dom->data = soap_strdup(soap, soap->tmpbuf); +#endif + return soap->tmpbuf; /* return non-null pointer */ +} +#endif + +/******************************************************************************/ +#if !defined(WITH_LEANER) || !defined(WITH_NOHTTP) +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getline(struct soap *soap, char *s, int len) +{ int i = len; + soap_wchar c = 0; + for (;;) + { while (--i > 0) + { c = soap_getchar(soap); + if (c == '\r' || c == '\n') + break; + if ((int)c == EOF) + return soap->error = SOAP_EOF; + *s++ = (char)c; + } + if (c != '\n') + c = soap_getchar(soap); /* got \r, now get \n */ + if (c == '\n') + { *s = '\0'; + if (i+1 == len) /* empty line: end of HTTP/MIME header */ + break; + c = soap_unget(soap, soap_getchar(soap)); + if (c != ' ' && c != '\t') /* HTTP line continuation? */ + break; + } + else if ((int)c == EOF) + return soap->error = SOAP_EOF; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static size_t +soap_count_attachments(struct soap *soap) +{ +#ifndef WITH_LEANER + register struct soap_multipart *content; + register size_t count = soap->count; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the message size with attachments, current count=%lu\n", (unsigned long)count)); + if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of DIME attachments\n")); + for (content = soap->dime.first; content; content = content->next) + { count += 12 + ((content->size+3)&(~3)); + if (content->id) + count += ((strlen(content->id)+3)&(~3)); + if (content->type) + count += ((strlen(content->type)+3)&(~3)); + if (content->options) + count += ((((unsigned char)content->options[2] << 8) | ((unsigned char)content->options[3]))+7)&(~3); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of DIME attachment content is %lu bytes\n", (unsigned long)content->size)); + } + } + if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary) + { register size_t n = strlen(soap->mime.boundary); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of MIME attachments\n")); + for (content = soap->mime.first; content; content = content->next) + { register const char *s; + /* count \r\n--boundary\r\n */ + count += 6 + n; + /* count Content-Type: ...\r\n */ + if (content->type) + count += 16 + strlen(content->type); + /* count Content-Transfer-Encoding: ...\r\n */ + s = soap_code_str(mime_codes, content->encoding); + if (s) + count += 29 + strlen(s); + /* count Content-ID: ...\r\n */ + if (content->id) + count += 14 + strlen(content->id); + /* count Content-Location: ...\r\n */ + if (content->location) + count += 20 + strlen(content->location); + /* count Content-Description: ...\r\n */ + if (content->description) + count += 23 + strlen(content->description); + /* count \r\n...content */ + count += 2 + content->size; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of MIME attachment content is %lu bytes\n", (unsigned long)content->size)); + } + /* count \r\n--boundary-- */ + count += 6 + n; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New count is %lu bytes\n", (unsigned long)count)); + return count; +#else + return soap->count; +#endif +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static int +soap_putdimefield(struct soap *soap, const char *s, size_t n) +{ if (soap_send_raw(soap, s, n)) + return soap->error; + return soap_send_raw(soap, SOAP_STR_PADDING, -(long)n&3); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_dime_option(struct soap *soap, unsigned short optype, const char *option) +{ size_t n; + char *s = NULL; + if (option) + { n = strlen(option); + s = (char*)soap_malloc(soap, n + 5); + if (s) + { s[0] = optype >> 8; + s[1] = optype & 0xFF; + s[2] = n >> 8; + s[3] = n & 0xFF; + strcpy(s + 4, option); + } + } + return s; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putdimehdr(struct soap *soap) +{ unsigned char tmp[12]; + size_t optlen = 0, idlen = 0, typelen = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Put DIME header id='%s'\n", soap->dime.id?soap->dime.id:"")); + if (soap->dime.options) + optlen = (((unsigned char)soap->dime.options[2] << 8) | ((unsigned char)soap->dime.options[3])) + 4; + if (soap->dime.id) + idlen = strlen(soap->dime.id); + if (soap->dime.type) + typelen = strlen(soap->dime.type); + tmp[0] = SOAP_DIME_VERSION | (soap->dime.flags & 0x7); + tmp[1] = soap->dime.flags & 0xF0; + tmp[2] = optlen >> 8; + tmp[3] = optlen & 0xFF; + tmp[4] = idlen >> 8; + tmp[5] = idlen & 0xFF; + tmp[6] = typelen >> 8; + tmp[7] = typelen & 0xFF; + tmp[8] = soap->dime.size >> 24; + tmp[9] = (soap->dime.size >> 16) & 0xFF; + tmp[10] = (soap->dime.size >> 8) & 0xFF; + tmp[11] = soap->dime.size & 0xFF; + if (soap_send_raw(soap, (char*)tmp, 12) + || soap_putdimefield(soap, soap->dime.options, optlen) + || soap_putdimefield(soap, soap->dime.id, idlen) + || soap_putdimefield(soap, soap->dime.type, typelen)) + return soap->error; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putdime(struct soap *soap) +{ struct soap_multipart *content; + if (!(soap->mode & SOAP_ENC_DIME)) + return SOAP_OK; + for (content = soap->dime.first; content; content = content->next) + { void *handle; + soap->dime.size = content->size; + soap->dime.id = content->id; + soap->dime.type = content->type; + soap->dime.options = content->options; + soap->dime.flags = SOAP_DIME_VERSION | SOAP_DIME_MEDIA; + if (soap->fdimereadopen && ((handle = soap->fdimereadopen(soap, (void*)content->ptr, content->id, content->type, content->options)) || soap->error)) + { size_t size = content->size; + if (!handle) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadopen failed\n")); + return soap->error; + } + if (!size && ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE)) + { size_t chunksize = sizeof(soap->tmpbuf); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming DIME\n")); + do + { size = soap->fdimeread(soap, handle, soap->tmpbuf, chunksize); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread returned %lu bytes\n", (unsigned long)size)); + if (size < chunksize) + { soap->dime.flags &= ~SOAP_DIME_CF; + if (!content->next) + soap->dime.flags |= SOAP_DIME_ME; + } + else + soap->dime.flags |= SOAP_DIME_CF; + soap->dime.size = size; + if (soap_putdimehdr(soap) + || soap_putdimefield(soap, soap->tmpbuf, size)) + break; + if (soap->dime.id) + { soap->dime.flags &= ~(SOAP_DIME_MB | SOAP_DIME_MEDIA); + soap->dime.id = NULL; + soap->dime.type = NULL; + soap->dime.options = NULL; + } + } while (size >= chunksize); + } + else + { if (!content->next) + soap->dime.flags |= SOAP_DIME_ME; + if (soap_putdimehdr(soap)) + return soap->error; + do + { size_t bufsize; + if (size < sizeof(soap->tmpbuf)) + bufsize = size; + else + bufsize = sizeof(soap->tmpbuf); + if (!(bufsize = soap->fdimeread(soap, handle, soap->tmpbuf, bufsize))) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size)); + soap->error = SOAP_EOF; + break; + } + if (soap_send_raw(soap, soap->tmpbuf, bufsize)) + break; + size -= bufsize; + } while (size); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n")); + soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3); + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n")); + if (soap->fdimereadclose) + soap->fdimereadclose(soap, handle); + } + else + { if (!content->next) + soap->dime.flags |= SOAP_DIME_ME; + if (soap_putdimehdr(soap) + || soap_putdimefield(soap, (char*)content->ptr, content->size)) + return soap->error; + } + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static char * +soap_getdimefield(struct soap *soap, size_t n) +{ register soap_wchar c; + register int i; + register char *s; + char *p = NULL; + if (n) + { p = (char*)soap_malloc(soap, n + 1); + if (p) + { s = p; + for (i = n; i > 0; i--) + { if ((int)(c = soap_get1(soap)) == EOF) + { soap->error = SOAP_EOF; + return NULL; + } + *s++ = (char)c; + } + *s = '\0'; + if ((soap->error = soap_move(soap, -(long)n&3))) + return NULL; + } + else + soap->error = SOAP_EOM; + } + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getdimehdr(struct soap *soap) +{ register soap_wchar c; + register char *s; + register int i; + unsigned char tmp[12]; + size_t optlen, idlen, typelen; + if (!(soap->mode & SOAP_ENC_DIME)) + return soap->error = SOAP_DIME_END; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME header\n")); + if (soap->dime.buflen || soap->dime.chunksize) + { if (soap_move(soap, (long)(soap->dime.size - soap_tell(soap)))) + return soap->error = SOAP_EOF; + soap_unget(soap, soap_getchar(soap)); /* skip padding and get hdr */ + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... From chunked\n")); + return SOAP_OK; + } + s = (char*)tmp; + for (i = 12; i > 0; i--) + { if ((int)(c = soap_getchar(soap)) == EOF) + return soap->error = SOAP_EOF; + *s++ = (char)c; + } + if ((tmp[0] & 0xF8) != SOAP_DIME_VERSION) + return soap->error = SOAP_DIME_MISMATCH; + soap->dime.flags = (tmp[0] & 0x7) | (tmp[1] & 0xF0); + optlen = (tmp[2] << 8) | tmp[3]; + idlen = (tmp[4] << 8) | tmp[5]; + typelen = (tmp[6] << 8) | tmp[7]; + soap->dime.size = (tmp[8] << 24) | (tmp[9] << 16) | (tmp[10] << 8) | tmp[11]; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME size=%lu flags=0x%X\n", (unsigned long)soap->dime.size, soap->dime.flags)); + if (!(soap->dime.options = soap_getdimefield(soap, optlen)) && soap->error) + return soap->error; + if (!(soap->dime.id = soap_getdimefield(soap, idlen)) && soap->error) + return soap->error; + if (!(soap->dime.type = soap_getdimefield(soap, typelen)) && soap->error) + return soap->error; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME id=%s, type=%s, options=%s\n", soap->dime.id?soap->dime.id:"", soap->dime.type?soap->dime.type:"", soap->dime.options?soap->dime.options+4:"")); + if (soap->dime.flags & SOAP_DIME_ME) + soap->mode &= ~SOAP_ENC_DIME; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getdime(struct soap *soap) +{ while (soap->dime.flags & SOAP_DIME_CF) + { if (soap_getdimehdr(soap)) + return soap->error; + if (soap_move(soap, soap->dime.size)) + return soap->error = SOAP_EOF; + } + if (soap_move(soap, ((soap->dime.size+3)&(~3))-soap_tell(soap))) + return soap->error = SOAP_EOF; + for (;;) + { register struct soap_multipart *content; + if (soap_getdimehdr(soap)) + break; + if (soap->fdimewriteopen && ((soap->dime.ptr = (char*)soap->fdimewriteopen(soap, soap->dime.id, soap->dime.type, soap->dime.options)) || soap->error)) + { const char *id, *type, *options; + size_t size, n; + if (!soap->dime.ptr) + return soap->error; + id = soap->dime.id; + type = soap->dime.type; + options = soap->dime.options; + for (;;) + { size = soap->dime.size; + for (;;) + { n = soap->buflen - soap->bufidx; + if (size < n) + n = size; + if ((soap->error = soap->fdimewrite(soap, (void*)soap->dime.ptr, soap->buf + soap->bufidx, n))) + break; + size -= n; + if (!size) + { soap->bufidx += n; + break; + } + if (soap_recv(soap)) + { soap->error = SOAP_EOF; + goto end; + } + } + if (soap_move(soap, -(long)soap->dime.size&3)) + { soap->error = SOAP_EOF; + break; + } + if (!(soap->dime.flags & SOAP_DIME_CF)) + break; + if (soap_getdimehdr(soap)) + break; + } +end: + if (soap->fdimewriteclose) + soap->fdimewriteclose(soap, (void*)soap->dime.ptr); + soap->dime.size = 0; + soap->dime.id = id; + soap->dime.type = type; + soap->dime.options = options; + } + else if (soap->dime.flags & SOAP_DIME_CF) + { const char *id, *type, *options; + register soap_wchar c; + register char *s; + register int i; + id = soap->dime.id; + type = soap->dime.type; + options = soap->dime.options; + if (soap_new_block(soap)) + return SOAP_EOM; + for (;;) + { s = (char*)soap_push_block(soap, soap->dime.size); + if (!s) + return soap->error = SOAP_EOM; + for (i = soap->dime.size; i > 0; i--) + { if ((int)(c = soap_get1(soap)) == EOF) + return soap->error = SOAP_EOF; + *s++ = (char)c; + } + if (soap_move(soap, -(long)soap->dime.size&3)) + return soap->error = SOAP_EOF; + if (!(soap->dime.flags & SOAP_DIME_CF)) + break; + if (soap_getdimehdr(soap)) + return soap->error; + } + soap->dime.size = soap->blist->size++; /* allocate one more for '\0' */ + if (!(soap->dime.ptr = soap_save_block(soap, NULL, 0))) + return soap->error; + soap->dime.ptr[soap->dime.size] = '\0'; /* force 0-terminated */ + soap->dime.id = id; + soap->dime.type = type; + soap->dime.options = options; + } + else + soap->dime.ptr = soap_getdimefield(soap, soap->dime.size); + content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, soap->dime.ptr, soap->dime.size); + if (!content) + return soap->error = SOAP_EOM; + content->id = soap->dime.id; + content->type = soap->dime.type; + content->options = soap->dime.options; + if (soap->error) + return soap->error; + soap_resolve_attachment(soap, content); + } + if (soap->error != SOAP_DIME_END) + return soap->error; + return soap->error = SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getmimehdr(struct soap *soap) +{ struct soap_multipart *content; + do + { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) + return soap->error; + } + while (!*soap->msgbuf); + if (soap->msgbuf[0] == '-' && soap->msgbuf[1] == '-') + { char *s = soap->msgbuf + strlen(soap->msgbuf) - 1; + /* remove white space */ + while (soap_blank(*s)) + s--; + s[1] = '\0'; + if (soap->mime.boundary) + { if (strcmp(soap->msgbuf + 2, soap->mime.boundary)) + return soap->error = SOAP_MIME_ERROR; + } + else + soap->mime.boundary = soap_strdup(soap, soap->msgbuf + 2); + if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) + return soap->error; + } + if (soap_set_mime_attachment(soap, NULL, 0, SOAP_MIME_NONE, NULL, NULL, NULL, NULL)) + return soap->error = SOAP_EOM; + content = soap->mime.last; + for (;;) + { register char *key = soap->msgbuf; + register char *val; + if (!*key) + break; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "MIME header: %s\n", key)); + val = strchr(soap->msgbuf, ':'); + if (val) + { *val = '\0'; + do val++; + while (*val && *val <= 32); + if (!soap_tag_cmp(key, "Content-ID")) + content->id = soap_strdup(soap, val); + else if (!soap_tag_cmp(key, "Content-Location")) + content->location = soap_strdup(soap, val); + else if (!soap_tag_cmp(key, "Content-Disposition")) + content->id = soap_strdup(soap, soap_get_header_attribute(soap, val, "name")); + else if (!soap_tag_cmp(key, "Content-Type")) + content->type = soap_strdup(soap, val); + else if (!soap_tag_cmp(key, "Content-Description")) + content->description = soap_strdup(soap, val); + else if (!soap_tag_cmp(key, "Content-Transfer-Encoding")) + content->encoding = (enum soap_mime_encoding)soap_code_int(mime_codes, val, (long)SOAP_MIME_NONE); + } + if (soap_getline(soap, key, sizeof(soap->msgbuf))) + return soap->error; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getmime(struct soap *soap) +{ while (soap_get_mime_attachment(soap, NULL)) + ; + return soap->error; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_post_check_mime_attachments(struct soap *soap) +{ soap->imode |= SOAP_MIME_POSTCHECK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_check_mime_attachments(struct soap *soap) +{ if (soap->mode & SOAP_MIME_POSTCHECK) + return soap_get_mime_attachment(soap, NULL) != NULL; + return 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +struct soap_multipart * +SOAP_FMAC2 +soap_get_mime_attachment(struct soap *soap, void *handle) +{ register soap_wchar c = 0; + register size_t i, m = 0; + register char *s, *t = NULL; + register struct soap_multipart *content; + register short flag = 0; + if (!(soap->mode & SOAP_ENC_MIME)) + return NULL; + content = soap->mime.last; + if (!content) + { if (soap_getmimehdr(soap)) + return NULL; + content = soap->mime.last; + } + else if (content != soap->mime.first) + { if (soap->fmimewriteopen && ((content->ptr = (char*)soap->fmimewriteopen(soap, (void*)handle, content->id, content->type, content->description, content->encoding)) || soap->error)) + { if (!content->ptr) + return NULL; + } + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Parsing MIME content id=%s type=%s\n", content->id?content->id:"", content->type?content->type:"")); + if (!content->ptr && soap_new_block(soap)) + { soap->error = SOAP_EOM; + return NULL; + } + for (;;) + { if (content->ptr) + s = soap->tmpbuf; + else if (!(s = (char*)soap_push_block(soap, sizeof(soap->tmpbuf)))) + { soap->error = SOAP_EOM; + return NULL; + } + for (i = 0; i < sizeof(soap->tmpbuf); i++) + { if (m > 0) + { *s++ = *t++; + m--; + } + else + { if (!flag) + { c = soap_get1(soap); + if ((int)c == EOF) + { soap->error = SOAP_EOF; + return NULL; + } + } + if (flag || c == '\r') + { t = soap->msgbuf; + memset(t, 0, sizeof(soap->msgbuf)); + strcpy(t, "\n--"); + if (soap->mime.boundary) + strncat(t, soap->mime.boundary, sizeof(soap->msgbuf)-4); + do c = soap_getchar(soap); + while (c == *t++); + if ((int)c == EOF) + { soap->error = SOAP_EOF; + return NULL; + } + if (!*--t) + goto end; + *t = (char)c; + flag = (c == '\r'); + m = t - soap->msgbuf + 1 - flag; + t = soap->msgbuf; + c = '\r'; + } + *s++ = (char)c; + } + } + if (content->ptr && soap->fmimewrite) + { if ((soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i))) + break; + } + } +end: + *s = '\0'; /* force 0-terminated */ + if (content->ptr) + { if (!soap->error && soap->fmimewrite) + soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i); + if (soap->fmimewriteclose) + soap->fmimewriteclose(soap, (void*)content->ptr); + if (soap->error) + return NULL; + } + else + { content->size = soap_size_block(soap, i+1)-1; + content->ptr = soap_save_block(soap, NULL, 0); + } + soap_resolve_attachment(soap, content); + if (c == '-' && soap_getchar(soap) == '-') + { soap->mode &= ~SOAP_ENC_MIME; + if ((soap->mode & SOAP_MIME_POSTCHECK) && soap_end_recv(soap)) + return NULL; + } + else + { while (c != '\r' && (int)c != EOF && soap_blank(c)) + c = soap_getchar(soap); + if (c != '\r' || soap_getchar(soap) != '\n') + { soap->error = SOAP_MIME_ERROR; + return NULL; + } + if (soap_getmimehdr(soap)) + return NULL; + } + return content; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_match_cid(struct soap *soap, const char *s, const char *t) +{ register size_t n; + if (!s) + return 1; + if (!strcmp(s, t)) + return 0; + if (!strncmp(s, "cid:", 4)) + s += 4; + n = strlen(t); + if (*t == '<') + { t++; + n -= 2; + } + if (!strncmp(s, t, n) && !s[n]) + return 0; + soap_decode(soap->tmpbuf, sizeof(soap->tmpbuf), s, SOAP_STR_EOS); + if (!strncmp(soap->tmpbuf, t, n) && !soap->tmpbuf[n]) + return 0; + return 1; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static void +soap_resolve_attachment(struct soap *soap, struct soap_multipart *content) +{ if (content->id) + { register struct soap_xlist **xp = &soap->xlist; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving attachment data for id=%s\n", content->id)); + while (*xp) + { register struct soap_xlist *xq = *xp; + if (!soap_match_cid(soap, xq->id, content->id)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Found matching attachment %s for content id=%s\n", xq->id, content->id)); + *xp = xq->next; + *xq->ptr = (unsigned char*)content->ptr; + *xq->size = (int)content->size; + *xq->type = (char*)content->type; + if (content->options) + *xq->options = (char*)content->options; + else + *xq->options = (char*)content->description; + SOAP_FREE(soap, xq); + } + else + xp = &(*xp)->next; + } + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putmimehdr(struct soap *soap, struct soap_multipart *content) +{ const char *s; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "MIME attachment type=%s\n", content->type?content->type:"")); + if (soap_send3(soap, "\r\n--", soap->mime.boundary, "\r\n")) + return soap->error; + if (content->type && soap_send3(soap, "Content-Type: ", content->type, "\r\n")) + return soap->error; + s = soap_code_str(mime_codes, content->encoding); + if (s && soap_send3(soap, "Content-Transfer-Encoding: ", s, "\r\n")) + return soap->error; + if (content->id && soap_send3(soap, "Content-ID: ", content->id, "\r\n")) + return soap->error; + if (content->location && soap_send3(soap, "Content-Location: ", content->location, "\r\n")) + return soap->error; + if (content->description && soap_send3(soap, "Content-Description: ", content->description, "\r\n")) + return soap->error; + return soap_send_raw(soap, "\r\n", 2); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putmime(struct soap *soap) +{ struct soap_multipart *content; + if (!(soap->mode & SOAP_ENC_MIME) || !soap->mime.boundary) + return SOAP_OK; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending MIME attachments\n")); + for (content = soap->mime.first; content; content = content->next) + { void *handle; + if (soap->fmimereadopen && ((handle = soap->fmimereadopen(soap, (void*)content->ptr, content->id, content->type, content->description)) || soap->error)) + { size_t size = content->size; + if (!handle) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimereadopen failed\n")); + return soap->error; + } + if (soap_putmimehdr(soap, content)) + return soap->error; + if (!size) + { if ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming MIME\n")); + do + { size = soap->fmimeread(soap, handle, soap->tmpbuf, sizeof(soap->tmpbuf)); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread returned %lu bytes\n", (unsigned long)size)); + if (soap_send_raw(soap, soap->tmpbuf, size)) + break; + } while (size); + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error: cannot chunk streaming MIME (no HTTP chunking)\n")); + } + } + else + { do + { size_t bufsize; + if (size < sizeof(soap->tmpbuf)) + bufsize = size; + else + bufsize = sizeof(soap->tmpbuf); + if (!(bufsize = soap->fmimeread(soap, handle, soap->tmpbuf, bufsize))) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size)); + soap->error = SOAP_EOF; + break; + } + if (soap_send_raw(soap, soap->tmpbuf, bufsize)) + break; + size -= bufsize; + } while (size); + } + if (soap->fmimereadclose) + soap->fmimereadclose(soap, handle); + } + else + { if (soap_putmimehdr(soap, content) + || soap_send_raw(soap, content->ptr, content->size)) + return soap->error; + } + } + return soap_send3(soap, "\r\n--", soap->mime.boundary, "--"); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_dime(struct soap *soap) +{ soap->omode |= SOAP_ENC_DIME; + soap->dime.first = NULL; + soap->dime.last = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_mime(struct soap *soap, const char *boundary, const char *start) +{ soap->omode |= SOAP_ENC_MIME; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = soap_strdup(soap, boundary); + soap->mime.start = soap_strdup(soap, start); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_clr_dime(struct soap *soap) +{ soap->omode &= ~SOAP_ENC_DIME; + soap->dime.first = NULL; + soap->dime.last = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_clr_mime(struct soap *soap) +{ soap->omode &= ~SOAP_ENC_MIME; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = NULL; + soap->mime.start = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static struct soap_multipart* +soap_new_multipart(struct soap *soap, struct soap_multipart **first, struct soap_multipart **last, char *ptr, size_t size) +{ struct soap_multipart *content; + content = (struct soap_multipart*)soap_malloc(soap, sizeof(struct soap_multipart)); + if (content) + { content->next = NULL; + content->ptr = ptr; + content->size = size; + content->id = NULL; + content->type = NULL; + content->options = NULL; + content->encoding = SOAP_MIME_NONE; + content->location = NULL; + content->description = NULL; + if (!*first) + *first = content; + if (*last) + (*last)->next = content; + *last = content; + } + return content; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_dime_attachment(struct soap *soap, char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option) +{ struct soap_multipart *content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, ptr, size); + if (!content) + return SOAP_EOM; + content->id = soap_strdup(soap, id); + content->type = soap_strdup(soap, type); + content->options = soap_dime_option(soap, optype, option); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_mime_attachment(struct soap *soap, char *ptr, size_t size, enum soap_mime_encoding encoding, const char *type, const char *id, const char *location, const char *description) +{ struct soap_multipart *content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, ptr, size); + if (!content) + return SOAP_EOM; + content->id = soap_strdup(soap, id); + content->type = soap_strdup(soap, type); + content->encoding = encoding; + content->location = soap_strdup(soap, location); + content->description = soap_strdup(soap, description); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +struct soap_multipart* +SOAP_FMAC2 +soap_next_multipart(struct soap_multipart *content) +{ if (content) + return content->next; + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static void +soap_select_mime_boundary(struct soap *soap) +{ while (!soap->mime.boundary || soap_valid_mime_boundary(soap)) + { register char *s = soap->mime.boundary; + register size_t n = 0; + if (s) + n = strlen(s); + if (n < 16) + { n = 64; + s = soap->mime.boundary = (char*)soap_malloc(soap, n + 1); + if (!s) + return; + } + strcpy(s, "=="); + s += 2; + n -= 4; + while (n) + { *s++ = soap_base64o[soap_random & 0x3F]; + n--; + } + strcpy(s, "=="); + } + if (!soap->mime.start) + soap->mime.start = ""; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static int +soap_valid_mime_boundary(struct soap *soap) +{ register struct soap_multipart *content; + register size_t k; + if (soap->fmimeread) + return SOAP_OK; + k = strlen(soap->mime.boundary); + for (content = soap->mime.first; content; content = content->next) + { if (content->ptr && content->size >= k) + { register const char *p = (const char*)content->ptr; + register size_t i; + for (i = 0; i < content->size - k; i++, p++) + { if (!strncmp(p, soap->mime.boundary, k)) + return SOAP_ERR; + } + } + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************\ + * + * HTTP cookie handling + * +\******************************************************************************/ + +#ifdef WITH_COOKIES +/******************************************************************************/ +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_encode_cookie(const char *s, char *t, size_t len) +{ register int c; + register size_t n = len; + while ((c = *s++) && --n > 0) + { if (c > ' ' && c < 128 && !strchr("()<>@,;:\\\"/[]?={}", c)) + *t++ = c; + else if (n > 2) + { *t++ = '%'; + *t++ = (c >> 4) + (c > 159 ? '7' : '0'); + c &= 0xF; + *t++ = c + (c > 9 ? '7' : '0'); + n -= 2; + } + else + break; + } + *t = '\0'; + return len - n; +} + +/******************************************************************************/ +SOAP_FMAC1 +struct soap_cookie* +SOAP_FMAC2 +soap_cookie(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + size_t n; + if (!domain) + domain = soap->cookie_domain; + if (!path) + path = soap->cookie_path; + if (!path) + path = SOAP_STR_EOS; + else if (*path == '/') + path++; + n = strlen(path); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Search cookie %s domain=%s path=%s\n", name, domain?domain:"(null)", path?path:"(null)")); + for (p = soap->cookies; p; p = p->next) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie in database: %s=%s domain=%s path=%s env=%hd\n", p->name, p->value?p->value:"(null)", p->domain?p->domain:"(null)", p->path?p->path:"(null)", p->env)); + if (!strcmp(p->name, name) + && p->domain + && p->path + && !strcmp(p->domain, domain) + && !strncmp(p->path, path, n)) + break; + } + return p; +} + +/******************************************************************************/ +SOAP_FMAC1 +struct soap_cookie* +SOAP_FMAC2 +soap_set_cookie(struct soap *soap, const char *name, const char *value, const char *domain, const char *path) +{ struct soap_cookie **p, *q; + int n; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set cookie: %s=%s domain=%s path=%s\n", name, value?value:"(null)", domain?domain:"(null)", path?path:"(null)")); + if (!domain) + domain = soap->cookie_domain; + if (!path) + path = soap->cookie_path; + if (!path) + path = SOAP_STR_EOS; + else if (*path == '/') + path++; + q = soap_cookie(soap, name, domain, path); + if (!q) + { if ((q = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie)))) + { if ((q->name = (char*)SOAP_MALLOC(soap, strlen(name)+1))) + strcpy(q->name, name); + q->value = NULL; + q->domain = NULL; + q->path = NULL; + q->expire = -1; + q->maxage = -1; + q->version = 1; + q->secure = 0; + q->modified = 0; + for (p = &soap->cookies, n = soap->cookie_max; *p && n; p = &(*p)->next, n--) + if (!strcmp((*p)->name, name) && (*p)->path && path && strcmp((*p)->path, path) < 0) + break; + if (n) + { q->next = *p; + *p = q; + } + else + { SOAP_FREE(soap, q->name); + SOAP_FREE(soap, q); + q = NULL; + } + } + } + else + q->modified = 1; + if (q) + { if (q->value) + { SOAP_FREE(soap, q->value); + q->value = NULL; + } + if (q->domain) + { SOAP_FREE(soap, q->domain); + q->domain = NULL; + } + if (q->path) + { SOAP_FREE(soap, q->path); + q->path = NULL; + } + if (value && *value && (q->value = (char*)SOAP_MALLOC(soap, strlen(value)+1))) + strcpy(q->value, value); + if (domain && (q->domain = (char*)SOAP_MALLOC(soap, strlen(domain)+1))) + strcpy(q->domain, domain); + if (path && (q->path = (char*)SOAP_MALLOC(soap, strlen(path)+1))) + strcpy(q->path, path); + q->session = 1; + q->env = 0; + } + return q; +} + +/******************************************************************************/ +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_clr_cookie(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie **p, *q; + if (!domain) + domain = soap->cookie_domain; + if (!domain) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error in clear cookie %s: cookie domain not set\n", name?name:"(null)")); + return; + } + if (!path) + path = soap->cookie_path; + if (!path) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error in clear cookie %s: cookie path not set\n", name?name:"(null)")); + return; + } + if (*path == '/') + path++; + for (p = &soap->cookies, q = *p; q; q = *p) + { if (!strcmp(q->name, name) && !strcmp(q->domain, domain) && !strncmp(q->path, path, strlen(q->path))) + { if (q->value) + SOAP_FREE(soap, q->value); + if (q->domain) + SOAP_FREE(soap, q->domain); + if (q->path) + SOAP_FREE(soap, q->path); + *p = q->next; + SOAP_FREE(soap, q); + } + else + p = &q->next; + } +} + +/******************************************************************************/ +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + return p->value; + return NULL; +} + +/******************************************************************************/ +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_env_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path)) && p->env) + return p->value; + return NULL; +} + +/******************************************************************************/ +SOAP_FMAC1 +time_t +SOAP_FMAC2 +soap_cookie_expire(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + return p->expire; + return -1; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_cookie_expire(struct soap *soap, const char *name, long expire, const char *domain, const char *path) +{ struct soap_cookie *p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set cookie expiration max-age %ld: %s domain=%s path=%s\n", expire, name, domain?domain:"(null)", path?path:"(null)")); + if ((p = soap_cookie(soap, name, domain, path))) + { p->maxage = expire; + p->modified = 1; + return SOAP_OK; + } + return SOAP_ERR; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + { p->session = 1; + p->modified = 1; + return SOAP_OK; + } + return SOAP_ERR; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_clr_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + { p->session = 0; + p->modified = 1; + return SOAP_OK; + } + return SOAP_ERR; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putsetcookies(struct soap *soap) +{ struct soap_cookie *p; + char *s, tmp[4096]; + const char *t; + for (p = soap->cookies; p; p = p->next) + { if (p->modified || !p->env) + { s = tmp; + if (p->name) + s += soap_encode_cookie(p->name, s, tmp-s+4064); + if (p->value && *p->value) + { *s++ = '='; + s += soap_encode_cookie(p->value, s, tmp-s+4064); + } + if (p->domain && (int)strlen(p->domain) < tmp-s+4064) + sprintf(s, ";Domain=\"%s\"", p->domain); + else if (soap->cookie_domain && (int)strlen(soap->cookie_domain) < tmp-s+4064) + sprintf(s, ";Domain=\"%s\"", soap->cookie_domain); + strcat(s, ";Path=/"); + if (p->path) + t = p->path; + else + t = soap->cookie_path; + if (t) + { if (*t == '/') + t++; + if ((int)strlen(t) < tmp-s+4064) + strcat(s, t); + } + s += strlen(s); + if (p->version > 0 && s-tmp < 4060) + { sprintf(s, ";Version=%u", p->version); + s += strlen(s); + } + if (p->maxage >= 0 && s-tmp < 4060) + { sprintf(s, ";Max-Age=%ld", p->maxage); + s += strlen(s); + } + if (p->secure && s-tmp < 4073) + strcpy(s, ";Secure"); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set-Cookie: %s\n", tmp)); + if ((soap->error = soap->fposthdr(soap, "Set-Cookie", tmp))) + return soap->error; + } + } + return SOAP_OK; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putcookies(struct soap *soap, const char *domain, const char *path, int secure) +{ struct soap_cookie **p, *q; + unsigned int version = 0; + time_t now = time(NULL); + char *s, tmp[4096]; + p = &soap->cookies; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending cookies for domain=%s path=%s\n", domain, path)); + if (*path == '/') + path++; + while ((q = *p)) + { if (q->expire && now > q->expire) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie %s expired\n", q->name)); + SOAP_FREE(soap, q->name); + if (q->value) + SOAP_FREE(soap, q->value); + if (q->domain) + SOAP_FREE(soap, q->domain); + if (q->path) + SOAP_FREE(soap, q->path); + *p = q->next; + SOAP_FREE(soap, q); + } + else + { size_t domlen = 0; + if (q->domain) + { const char *s = strchr(q->domain, ':'); + if (s) + domlen = s - q->domain; + else + domlen = strlen(q->domain); + } + if ((!q->domain || !strncmp(q->domain, domain, domlen)) + && (!q->path || !strncmp(q->path, path, strlen(q->path))) + && (!q->secure || secure)) + { s = tmp; + if (q->version != version) + { sprintf(s, "$Version=%u;", q->version); + version = q->version; + } + if (q->name) + s += soap_encode_cookie(q->name, s, tmp-s+4080); + if (q->value && *q->value) + { *s++ = '='; + s += soap_encode_cookie(q->value, s, tmp-s+4080); + } + if (q->path && *q->path && (int)strlen(q->path) < tmp-s+4080) + { sprintf(s, ";$Path=\"/%s\"", (*q->path == '/' ? q->path + 1 : q->path)); + s += strlen(s); + } + if (q->domain && (int)strlen(q->domain) < tmp-s+4080) + sprintf(s, ";$Domain=\"%s\"", q->domain); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie: %s\n", tmp)); + if ((soap->error = soap->fposthdr(soap, "Cookie", tmp))) + return soap->error; + } + p = &q->next; + } + } + return SOAP_OK; +} + +/******************************************************************************/ +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_getcookies(struct soap *soap, const char *val) +{ struct soap_cookie *p = NULL, *q; + const char *s; + char *t, tmp[4096]; /* cookie size is up to 4096 bytes [RFC2109] */ + char *domain = NULL; + char *path = NULL; + unsigned int version = 0; + time_t now = time(NULL); + if (!val) + return; + s = val; + while (*s) + { s = soap_decode_key(tmp, sizeof(tmp), s); + if (!soap_tag_cmp(tmp, "$Version")) + { if ((s = soap_decode_val(tmp, sizeof(tmp), s))) + { if (p) + p->version = (int)atol(tmp); + else + version = (int)atol(tmp); + } + } + else if (!soap_tag_cmp(tmp, "$Path")) + { s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) + strcpy(t, tmp); + } + else + t = NULL; + if (p) + { if (p->path) + SOAP_FREE(soap, p->path); + p->path = t; + } + else + { if (path) + SOAP_FREE(soap, path); + path = t; + } + } + else if (!soap_tag_cmp(tmp, "$Domain")) + { s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) + strcpy(t, tmp); + } + else + t = NULL; + if (p) + { if (p->domain) + SOAP_FREE(soap, p->domain); + p->domain = t; + } + else + { if (domain) + SOAP_FREE(soap, domain); + domain = t; + } + } + else if (p && !soap_tag_cmp(tmp, "Path")) + { if (p->path) + SOAP_FREE(soap, p->path); + s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { if ((p->path = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) + strcpy(p->path, tmp); + } + else + p->path = NULL; + } + else if (p && !soap_tag_cmp(tmp, "Domain")) + { if (p->domain) + SOAP_FREE(soap, p->domain); + s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { if ((p->domain = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) + strcpy(p->domain, tmp); + } + else + p->domain = NULL; + } + else if (p && !soap_tag_cmp(tmp, "Version")) + { s = soap_decode_val(tmp, sizeof(tmp), s); + p->version = (unsigned int)atol(tmp); + } + else if (p && !soap_tag_cmp(tmp, "Max-Age")) + { s = soap_decode_val(tmp, sizeof(tmp), s); + p->expire = now + atol(tmp); + } + else if (p && !soap_tag_cmp(tmp, "Expires")) + { struct tm T; + char a[3]; + static const char mns[] = "anebarprayunulugepctovec"; + s = soap_decode_val(tmp, sizeof(tmp), s); + if (strlen(tmp) > 20) + { memset((void*)&T, 0, sizeof(T)); + a[0] = tmp[4]; + a[1] = tmp[5]; + a[2] = '\0'; + T.tm_mday = (int)atol(a); + a[0] = tmp[8]; + a[1] = tmp[9]; + T.tm_mon = (strstr(mns, a) - mns) / 2; + a[0] = tmp[11]; + a[1] = tmp[12]; + T.tm_year = 100 + (int)atol(a); + a[0] = tmp[13]; + a[1] = tmp[14]; + T.tm_hour = (int)atol(a); + a[0] = tmp[16]; + a[1] = tmp[17]; + T.tm_min = (int)atol(a); + a[0] = tmp[19]; + a[1] = tmp[20]; + T.tm_sec = (int)atol(a); + p->expire = soap_timegm(&T); + } + } + else if (p && !soap_tag_cmp(tmp, "Secure")) + p->secure = 1; + else + { if (p) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie %s=%s domain=%s path=%s expire=%ld secure=%d\n", p->name, p->value?p->value:"(null)", p->domain?p->domain:"(null)", p->path?p->path:"(null)", p->expire, p->secure)); + if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path))) + { q->version = p->version; + q->expire = p->expire; + q->secure = p->secure; + q->env = 1; + } + if (p->name) + SOAP_FREE(soap, p->name); + if (p->value) + SOAP_FREE(soap, p->value); + if (p->domain) + SOAP_FREE(soap, p->domain); + if (p->path) + SOAP_FREE(soap, p->path); + SOAP_FREE(soap, p); + } + if ((p = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie)))) + { p->name = (char*)SOAP_MALLOC(soap, strlen(tmp)+1); + strcpy(p->name, tmp); + s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { p->value = (char*)SOAP_MALLOC(soap, strlen(tmp)+1); + strcpy(p->value, tmp); + } + else + p->value = NULL; + if (domain) + p->domain = domain; + else + { p->domain = (char*)SOAP_MALLOC(soap, strlen(soap->host)+1); + strcpy(p->domain, soap->host); + } + if (path) + p->path = path; + else + { p->path = (char*)SOAP_MALLOC(soap, strlen(soap->path)+1); + strcpy(p->path, soap->path); + } + p->expire = 0; + p->secure = 0; + p->version = version; + } + } + } + if (p) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie %s=%s domain=%s path=%s expire=%ld secure=%d\n", p->name, p->value?p->value:"(null)", p->domain?p->domain:"(null)", p->path?p->path:"(null)", p->expire, p->secure)); + if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path))) + { q->version = p->version; + q->expire = p->expire; + q->secure = p->secure; + q->env = 1; + } + if (p->name) + SOAP_FREE(soap, p->name); + if (p->value) + SOAP_FREE(soap, p->value); + if (p->domain) + SOAP_FREE(soap, p->domain); + if (p->path) + SOAP_FREE(soap, p->path); + SOAP_FREE(soap, p); + } + if (domain) + SOAP_FREE(soap, domain); + if (path) + SOAP_FREE(soap, path); +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getenv_cookies(struct soap *soap) +{ struct soap_cookie *p; + const char *s; + char key[4096], val[4096]; /* cookie size is up to 4096 bytes [RFC2109] */ + if (!(s = getenv("HTTP_COOKIE"))) + return SOAP_ERR; + do + { s = soap_decode_key(key, sizeof(key), s); + s = soap_decode_val(val, sizeof(val), s); + p = soap_set_cookie(soap, key, val, NULL, NULL); + if (p) + p->env = 1; + } while (*s); + return SOAP_OK; +} + +/******************************************************************************/ +SOAP_FMAC1 +struct soap_cookie* +SOAP_FMAC2 +soap_copy_cookies(struct soap *copy, struct soap *soap) +{ struct soap_cookie *p, **q, *r; + q = &r; + for (p = soap->cookies; p; p = p->next) + { if (!(*q = (struct soap_cookie*)SOAP_MALLOC(copy, sizeof(struct soap_cookie)))) + return r; + **q = *p; + if (p->name) + { if (((*q)->name = (char*)SOAP_MALLOC(copy, strlen(p->name)+1))) + strcpy((*q)->name, p->name); + } + if (p->value) + { if (((*q)->value = (char*)SOAP_MALLOC(copy, strlen(p->value)+1))) + strcpy((*q)->value, p->value); + } + if (p->domain) + { if (((*q)->domain = (char*)SOAP_MALLOC(copy, strlen(p->domain)+1))) + strcpy((*q)->domain, p->domain); + } + if (p->path) + { if (((*q)->path = (char*)SOAP_MALLOC(copy, strlen(p->path)+1))) + strcpy((*q)->path, p->path); + } + q = &(*q)->next; + } + *q = NULL; + return r; +} + +/******************************************************************************/ +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_free_cookies(struct soap *soap) +{ struct soap_cookie *p; + for (p = soap->cookies; p; p = soap->cookies) + { soap->cookies = p->next; + SOAP_FREE(soap, p->name); + if (p->value) + SOAP_FREE(soap, p->value); + if (p->domain) + SOAP_FREE(soap, p->domain); + if (p->path) + SOAP_FREE(soap, p->path); + SOAP_FREE(soap, p); + } +} + +/******************************************************************************/ +#endif /* WITH_COOKIES */ + +/******************************************************************************/ +#ifdef WITH_GZIP +#ifndef PALM_1 +static int +soap_getgziphdr(struct soap *soap) +{ int i; + soap_wchar c, f = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get gzip header\n")); + for (i = 0; i < 9; i++) + { if ((int)(c = soap_get1(soap) == EOF)) + return soap->error = SOAP_EOF; + if (i == 2) + f = c; + } + if (f & 0x04) /* FEXTRA */ + { for (i = soap_get1(soap) | (soap_get1(soap) << 8); i; i--) + { if ((int)soap_get1(soap) == EOF) + return soap->error = SOAP_EOF; + } + } + if (f & 0x08) /* FNAME */ + { do + c = soap_get1(soap); + while (c && (int)c != EOF); + } + if ((int)c != EOF && (f & 0x10)) /* FCOMMENT */ + { do + c = soap_get1(soap); + while (c && (int)c != EOF); + } + if ((int)c != EOF && (f & 0x01)) /* FHCRC */ + { if ((int)(c = soap_get1(soap)) != EOF) + c = soap_get1(soap); + } + if ((int)c == EOF) + return soap->error = SOAP_EOF; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_begin_recv(struct soap *soap) +{ soap_wchar c; + soap->error = SOAP_OK; + soap_free_temp(soap); + soap_set_local_namespaces(soap); + soap->version = 0; /* don't assume we're parsing SOAP content by default */ +#ifndef WITH_NOIDREF + soap_free_iht(soap); +#endif + if ((soap->imode & SOAP_IO) == SOAP_IO_CHUNK) + soap->omode |= SOAP_IO_CHUNK; + soap->imode &= ~SOAP_IO; + soap->mode = soap->imode; + if (!soap->keep_alive) + { soap->buflen = 0; + soap->bufidx = 0; + } + if (!(soap->mode & SOAP_IO_KEEPALIVE)) + soap->keep_alive = 0; + soap->ahead = 0; + soap->peeked = 0; + soap->level = 0; + soap->part = SOAP_BEGIN; + soap->alloced = 0; + soap->count = 0; + soap->length = 0; + soap->cdata = 0; + *soap->endpoint = '\0'; + soap->action = NULL; + soap->status = 0; +#ifndef WITH_LEANER + soap->dom = NULL; + soap->dime.chunksize = 0; + soap->dime.buflen = 0; + soap->dime.list = NULL; + soap->dime.first = NULL; + soap->dime.last = NULL; + soap->mime.list = NULL; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = NULL; + soap->mime.start = NULL; + soap->xlist = NULL; +#endif +#ifdef WIN32 +#ifndef UNDER_CE +#ifndef WITH_FASTCGI + if (!soap_valid_socket(soap->socket)) +#ifdef __BORLANDC__ + setmode((SOAP_SOCKET)soap->recvfd, O_BINARY); +#else + _setmode((SOAP_SOCKET)soap->recvfd, _O_BINARY); +#endif +#endif +#endif +#endif +#ifdef WITH_ZLIB + soap->mode &= ~SOAP_ENC_ZLIB; + soap->zlib_in = SOAP_ZLIB_NONE; + soap->zlib_out = SOAP_ZLIB_NONE; + soap->d_stream.next_in = Z_NULL; + soap->d_stream.avail_in = 0; + soap->d_stream.next_out = (Byte*)soap->buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + soap->z_ratio_in = 1.0; +#endif +#ifndef WITH_LEANER + if (soap->fprepareinit) + soap->fprepareinit(soap); +#endif + c = soap_getchar(soap); +#ifdef WITH_GZIP + if (c == 0x1F) + { if (soap_getgziphdr(soap)) + return soap->error; + if (inflateInit2(&soap->d_stream, -MAX_WBITS) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; + soap->zlib_state = SOAP_ZLIB_INFLATE; + soap->mode |= SOAP_ENC_ZLIB; + soap->zlib_in = SOAP_ZLIB_GZIP; + soap->z_crc = crc32(0L, NULL, 0); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n")); + memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); + /* should not chunk over plain transport, so why bother to check? */ + /* if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) */ + /* soap->z_buflen = soap->bufidx; */ + /* else */ + soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx); + soap->d_stream.avail_in = soap->buflen - soap->bufidx; + soap->z_buflen = soap->buflen; + soap->buflen = soap->bufidx; + c = soap_getchar(soap); + } +#endif +#ifndef WITH_LEANER + if (c == '-' && soap_get0(soap) == '-') + soap->mode |= SOAP_ENC_MIME; + else if ((c & 0xFFFC) == (SOAP_DIME_VERSION | SOAP_DIME_MB) && (soap_get0(soap) & 0xFFF0) == 0x20) + soap->mode |= SOAP_ENC_DIME; + else +#endif + { while (soap_blank(c)) + c = soap_getchar(soap); + } + if ((int)c == EOF) + return soap->error = SOAP_EOF; + soap_unget(soap, c); +#ifndef WITH_NOHTTP + /* if not XML or (start of)BOM or MIME/DIME/ZLIB, assume HTTP header */ + if (c != '<' && c != 0xEF && !(soap->mode & (SOAP_ENC_MIME | SOAP_ENC_DIME | SOAP_ENC_ZLIB))) + { soap->mode &= ~SOAP_IO; + soap->error = soap->fparse(soap); + if (soap->error && soap->error < SOAP_STOP) + { soap->keep_alive = 0; /* force close later */ + return soap->error; + } + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) + { soap->chunkbuflen = soap->buflen; + soap->buflen = soap->bufidx; + soap->chunksize = 0; + } +#ifndef WITH_LEANER + else if (soap->fpreparerecv && soap->buflen != soap->bufidx) + soap->fpreparerecv(soap, soap->buf + soap->bufidx, soap->buflen - soap->bufidx); +#endif + /* Note: fparse should not use soap_unget to push back last char */ + if (soap_get0(soap) == (int)EOF) + { if (soap->status == 200) + return soap->error = SOAP_NO_DATA; + return soap->error = soap->status; + } +#ifdef WITH_ZLIB + if (soap->zlib_in != SOAP_ZLIB_NONE) +#ifdef WITH_GZIP + { c = soap_get1(soap); + if (c == 0x1F) + { if (soap_getgziphdr(soap)) + return soap->error; + if (inflateInit2(&soap->d_stream, -MAX_WBITS) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; + soap->zlib_state = SOAP_ZLIB_INFLATE; + soap->z_crc = crc32(0L, NULL, 0); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n")); + } + else + { soap_revget1(soap); +#else + { +#endif + if (inflateInit(&soap->d_stream) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; + soap->zlib_state = SOAP_ZLIB_INFLATE; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate initialized\n")); + } + soap->mode |= SOAP_ENC_ZLIB; + memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); + soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx); + soap->d_stream.avail_in = soap->buflen - soap->bufidx; + soap->z_buflen = soap->buflen; + soap->buflen = soap->bufidx; + } +#endif + if (soap->error) + { if (soap->error == SOAP_FORM && soap->fform) + { soap->error = soap->fform(soap); + if (soap->error == SOAP_OK) + soap->error = SOAP_STOP; /* prevents further processing */ + } + return soap->error; + } + } +#endif +#ifndef WITH_LEANER + if (soap->mode & SOAP_ENC_MIME) + { if (soap_getmimehdr(soap)) + return soap->error; + if (soap->mime.start) + { do + { if (!soap->mime.last->id) + break; + if (!soap_match_cid(soap, soap->mime.start, soap->mime.last->id)) + break; + } while (soap_get_mime_attachment(soap, NULL)); + } + if (soap_get_header_attribute(soap, soap->mime.first->type, "application/dime")) + soap->mode |= SOAP_ENC_DIME; + } + if (soap->mode & SOAP_ENC_DIME) + { if (soap_getdimehdr(soap)) + return soap->error; + if (soap->dime.flags & SOAP_DIME_CF) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked DIME SOAP message\n")); + soap->dime.chunksize = soap->dime.size; + if (soap->buflen - soap->bufidx >= soap->dime.chunksize) + { soap->dime.buflen = soap->buflen; + soap->buflen = soap->bufidx + soap->dime.chunksize; + } + else + soap->dime.chunksize -= soap->buflen - soap->bufidx; + } + soap->count = soap->buflen - soap->bufidx; + } +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_parse(struct soap *soap) +{ char header[SOAP_HDRLEN], *s; + unsigned short get = 0, status = 0, k = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Waiting for HTTP request/response...\n")); + *soap->endpoint = '\0'; + soap->length = 0; + soap->userid = NULL; + soap->passwd = NULL; + soap->action = NULL; + soap->authrealm = NULL; + do + { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) + return soap->error; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP status: %s\n", soap->msgbuf)); + for (;;) + { if (soap_getline(soap, header, SOAP_HDRLEN)) + { if (soap->error == SOAP_EOF) + { soap->error = SOAP_OK; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "EOF in HTTP header, continue anyway\n")); + break; + } + return soap->error; + } + if (!*header) + break; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP header: %s\n", header)); + s = strchr(header, ':'); + if (s) + { *s = '\0'; + do s++; + while (*s && *s <= 32); + if ((soap->error = soap->fparsehdr(soap, header, s))) + { if (soap->error < SOAP_STOP) + return soap->error; + status = soap->error; + soap->error = SOAP_OK; + } + } + } + if ((s = strchr(soap->msgbuf, ' '))) + { k = (unsigned short)soap_strtoul(s, &s, 10); + if (!soap_blank(*s)) + k = 0; + } + else + k = 0; + } while (k == 100); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Finished HTTP header parsing, status = %d\n", k)); + s = strstr(soap->msgbuf, "HTTP/"); + if (s && s[7] != '1') + { if (soap->keep_alive == 1) + soap->keep_alive = 0; + if (k == 0 && (soap->omode & SOAP_IO) == SOAP_IO_CHUNK) /* k == 0 for HTTP request */ + { soap->imode |= SOAP_IO_CHUNK; + soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE; + } + } + if (soap->keep_alive < 0) + soap->keep_alive = 1; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Keep alive connection = %d\n", soap->keep_alive)); + if (s && (((get = !strncmp(soap->msgbuf, "GET ", 4))) || !strncmp(soap->msgbuf, "POST ", 5))) + { size_t m = strlen(soap->endpoint); + size_t n = m + (s - soap->msgbuf) - 5 - (!get); + if (n >= sizeof(soap->endpoint)) + n = sizeof(soap->endpoint) - 1; + strncpy(soap->path, soap->msgbuf + 4 + (!get), n - m); + soap->path[n - m] = '\0'; + strcat(soap->endpoint, soap->path); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Target endpoint='%s'\n", soap->endpoint)); + if (get) + { soap->error = soap->fget(soap); + if (soap->error == SOAP_OK) + soap->error = SOAP_STOP; /* prevents further processing */ + return soap->error; + } + if (status) + return soap->error = status; + } + soap->status = k; + if (k == 0 || k == 200 || (((k > 200 && k <= 299) || k == 400 || k == 500) && ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK || soap->length > 0))) + return SOAP_OK; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP error %d\n", k)); + return soap_set_receiver_error(soap, "HTTP Error", soap->msgbuf, k); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_parse_header(struct soap *soap, const char *key, const char *val) +{ if (!soap_tag_cmp(key, "Host")) + { +#ifdef WITH_OPENSSL + if (soap->imode & SOAP_ENC_SSL) + strcpy(soap->endpoint, "https://"); + else +#endif + strcpy(soap->endpoint, "http://"); + strncat(soap->endpoint, val, sizeof(soap->endpoint) - 8); + soap->endpoint[sizeof(soap->endpoint) - 1] = '\0'; + } +#ifndef WITH_LEANER + else if (!soap_tag_cmp(key, "Content-Type")) + { soap->http_content = soap_strdup(soap, val); + if (soap_get_header_attribute(soap, val, "application/dime")) + soap->mode |= SOAP_ENC_DIME; + else if (soap_get_header_attribute(soap, val, "multipart/related") + || soap_get_header_attribute(soap, val, "multipart/form-data")) + { soap->mime.boundary = soap_strdup(soap, soap_get_header_attribute(soap, val, "boundary")); + soap->mime.start = soap_strdup(soap, soap_get_header_attribute(soap, val, "start")); + soap->mode |= SOAP_ENC_MIME; + } + } +#endif + else if (!soap_tag_cmp(key, "Content-Length")) + soap->length = soap_strtoul(val, NULL, 10); + else if (!soap_tag_cmp(key, "Content-Encoding")) + { if (!soap_tag_cmp(val, "deflate")) +#ifdef WITH_ZLIB + soap->zlib_in = SOAP_ZLIB_DEFLATE; +#else + return SOAP_ZLIB_ERROR; +#endif + else if (!soap_tag_cmp(val, "gzip")) +#ifdef WITH_GZIP + soap->zlib_in = SOAP_ZLIB_GZIP; +#else + return SOAP_ZLIB_ERROR; +#endif + } +#ifdef WITH_ZLIB + else if (!soap_tag_cmp(key, "Accept-Encoding")) + { +#ifdef WITH_GZIP + if (strchr(val, '*') || soap_get_header_attribute(soap, val, "gzip")) + soap->zlib_out = SOAP_ZLIB_GZIP; + else +#endif + if (strchr(val, '*') || soap_get_header_attribute(soap, val, "deflate")) + soap->zlib_out = SOAP_ZLIB_DEFLATE; + else + soap->zlib_out = SOAP_ZLIB_NONE; + } +#endif + else if (!soap_tag_cmp(key, "Transfer-Encoding")) + { soap->mode &= ~SOAP_IO; + if (!soap_tag_cmp(val, "chunked")) + soap->mode |= SOAP_IO_CHUNK; + } + else if (!soap_tag_cmp(key, "Connection")) + { if (!soap_tag_cmp(val, "keep-alive")) + soap->keep_alive = -soap->keep_alive; + else if (!soap_tag_cmp(val, "close")) + soap->keep_alive = 0; + } +#ifndef WITH_LEAN + else if (!soap_tag_cmp(key, "Authorization")) + { if (!soap_tag_cmp(val, "Basic *")) + { int n; + char *s; + soap_base642s(soap, val + 6, soap->tmpbuf, sizeof(soap->tmpbuf) - 1, &n); + soap->tmpbuf[n] = '\0'; + if ((s = strchr(soap->tmpbuf, ':'))) + { *s = '\0'; + soap->userid = soap_strdup(soap, soap->tmpbuf); + soap->passwd = soap_strdup(soap, s + 1); + } + } + } + else if (!soap_tag_cmp(key, "WWW-Authenticate")) + soap->authrealm = soap_strdup(soap, soap_get_header_attribute(soap, val + 6, "realm")); + else if (!soap_tag_cmp(key, "Expect")) + { if (!soap_tag_cmp(val, "100-continue")) + { if ((soap->error = soap->fposthdr(soap, "HTTP/1.1 100 Continue", NULL)) + || (soap->error = soap->fposthdr(soap, NULL, NULL))) + return soap->error; + } + } +#endif + else if (!soap_tag_cmp(key, "SOAPAction")) + { if (*val == '"') + { soap->action = soap_strdup(soap, val + 1); + soap->action[strlen(soap->action) - 1] = '\0'; + } + } + else if (!soap_tag_cmp(key, "Location")) + { strncpy(soap->endpoint, val, sizeof(soap->endpoint)); + soap->endpoint[sizeof(soap->endpoint) - 1] = '\0'; + } +#ifdef WITH_COOKIES + else if (!soap_tag_cmp(key, "Cookie") + || !soap_tag_cmp(key, "Cookie2") + || !soap_tag_cmp(key, "Set-Cookie") + || !soap_tag_cmp(key, "Set-Cookie2")) + soap_getcookies(soap, val); +#endif + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_get_header_attribute(struct soap *soap, const char *line, const char *key) +{ register const char *s = line; + if (s) + { while (*s) + { register short flag; + s = soap_decode_key(soap->tmpbuf, sizeof(soap->tmpbuf), s); + flag = soap_tag_cmp(soap->tmpbuf, key); + s = soap_decode_val(soap->tmpbuf, sizeof(soap->tmpbuf), s); + if (!flag) + return soap->tmpbuf; + } + } + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_decode_key(char *buf, size_t len, const char *val) +{ return soap_decode(buf, len, val, "=,;"); +} +#endif +#endif + +/******************************************************************************/ +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_decode_val(char *buf, size_t len, const char *val) +{ if (*val != '=') + { *buf = '\0'; + return val; + } + return soap_decode(buf, len, val + 1, ",;"); +} +#endif +#endif + +/******************************************************************************/ +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +#ifndef PALM_1 +static const char* +soap_decode(char *buf, size_t len, const char *val, const char *sep) +{ const char *s; + char *t = buf; + for (s = val; *s; s++) + if (*s != ' ' && *s != '\t' && !strchr(sep, *s)) + break; + if (*s == '"') + { s++; + while (*s && *s != '"' && --len) + *t++ = *s++; + } + else + { while (soap_notblank(*s) && !strchr(sep, *s) && --len) + { if (*s == '%') + { *t++ = ((s[1] >= 'A' ? (s[1] & 0x7) + 9 : s[1] - '0') << 4) + + (s[2] >= 'A' ? (s[2] & 0x7) + 9 : s[2] - '0'); + s += 3; + } + else + *t++ = *s++; + } + } + *t = '\0'; + while (*s && !strchr(sep, *s)) + s++; + return s; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_envelope_begin_out(struct soap *soap) +{ +#ifndef WITH_LEANER + size_t n = 0; + if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && soap->mime.start && strlen(soap->mime.boundary) + strlen(soap->mime.start) < sizeof(soap->tmpbuf) - 80 ) + { const char *s; + if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) + s = "application/dime"; + else if (soap->version == 2) + { if (soap->mode & SOAP_ENC_MTOM) + s = "application/xop+xml; charset=utf-8; type=application/soap+xml"; + else + s = "application/soap+xml; charset=utf-8"; + } + else + s = "text/xml; charset=utf-8"; + sprintf(soap->tmpbuf, "--%s\r\nContent-Type: %s\r\nContent-Transfer-Encoding: binary\r\nContent-ID: %s\r\n\r\n", soap->mime.boundary, s, soap->mime.start); + n = strlen(soap->tmpbuf); + if (soap_send_raw(soap, soap->tmpbuf, n)) + return soap->error; + } + if (soap->mode & SOAP_IO_LENGTH) + soap->dime.size = soap->count; /* DIME in MIME correction */ + if (!(soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME)) + { if (soap_putdimehdr(soap)) + return soap->error; + } +#endif + soap->part = SOAP_IN_ENVELOPE; + return soap_element_begin_out(soap, "SOAP-ENV:Envelope", 0, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_envelope_end_out(struct soap *soap) +{ if (soap_element_end_out(soap, "SOAP-ENV:Envelope")) + return soap->error; +#ifndef WITH_LEANER + if ((soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) + { soap->dime.size = soap->count - soap->dime.size; /* DIME in MIME correction */ + sprintf(soap->id, soap->dime_id_format, 0); + soap->dime.id = soap->id; + if (soap->local_namespaces) + { if (soap->local_namespaces[0].out) + soap->dime.type = (char*)soap->local_namespaces[0].out; + else + soap->dime.type = (char*)soap->local_namespaces[0].ns; + } + soap->dime.options = NULL; + soap->dime.flags = SOAP_DIME_MB | SOAP_DIME_ABSURI; + if (!soap->dime.first) + soap->dime.flags |= SOAP_DIME_ME; + soap->count += 12 + ((strlen(soap->dime.id)+3)&(~3)) + (soap->dime.type ? ((strlen(soap->dime.type)+3)&(~3)) : 0); + } + if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) + return soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3); +#endif + soap->part = SOAP_END_ENVELOPE; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_envelope_begin_in(struct soap *soap) +{ register struct Namespace *p; + soap->part = SOAP_IN_ENVELOPE; + if (soap_element_begin_in(soap, "SOAP-ENV:Envelope", 0, NULL)) + { +#ifndef WITH_LEAN + if (!soap_element_begin_in(soap, "html", 0, NULL)) + { /* get HTML from buffer, stop receiving to avoid HTML parsing issues */ + char *s; +#ifndef WITH_NOIO + size_t (*f)(struct soap*, char*, size_t) = soap->frecv; + soap->frecv = frecv_stop; +#endif + soap_revert(soap); + s = soap_string_in(soap, 1, -1, -1); +#ifndef WITH_NOIO + soap->frecv = f; +#endif + return soap_set_receiver_error(soap, "HTTP Error", s, SOAP_HTTP_ERROR); + } +#endif + return soap->error = SOAP_VERSIONMISMATCH; + } + p = soap->local_namespaces; + if (p) + { const char *ns = p[0].out; + if (!ns) + ns = p[0].ns; + if (!strcmp(ns, soap_env1)) + { soap->version = 1; /* make sure we use SOAP 1.1 */ + if (p[1].out) + SOAP_FREE(soap, p[1].out); + if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc1)))) + strcpy(p[1].out, soap_enc1); + } + else if (!strcmp(ns, soap_env2)) + { soap->version = 2; /* make sure we use SOAP 1.2 */ + if (p[1].out) + SOAP_FREE(soap, p[1].out); + if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc2)))) + strcpy(p[1].out, soap_enc2); + } + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_envelope_end_in(struct soap *soap) +{ soap->part = SOAP_END_ENVELOPE; + return soap_element_end_in(soap, "SOAP-ENV:Envelope"); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_body_begin_out(struct soap *soap) +{ soap->part = SOAP_IN_BODY; + if (soap->version == 1) + soap->encoding = 1; +#ifndef WITH_LEAN + if ((soap->mode & SOAP_XML_SEC) && soap_set_attr(soap, "wsu:Id", "Body")) + return soap->error; +#endif + if (soap_element(soap, "SOAP-ENV:Body", 0, NULL)) + return soap->error; + return soap_element_start_end_out(soap, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_body_end_out(struct soap *soap) +{ if (soap_element_end_out(soap, "SOAP-ENV:Body")) + return soap->error; + soap->part = SOAP_END_BODY; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_body_begin_in(struct soap *soap) +{ soap->part = SOAP_IN_BODY; + if (soap_element_begin_in(soap, "SOAP-ENV:Body", 0, NULL)) + return soap->error; + if (!soap->body) + soap->part = SOAP_NO_BODY; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_body_end_in(struct soap *soap) +{ if (soap->part == SOAP_NO_BODY) + return SOAP_OK; + soap->part = SOAP_END_BODY; + return soap_element_end_in(soap, "SOAP-ENV:Body"); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv_header(struct soap *soap) +{ if (soap_getheader(soap) && soap->error == SOAP_TAG_MISMATCH) + soap->error = SOAP_OK; + else if (soap->error == SOAP_OK && soap->fheader) + soap->error = soap->fheader(soap); + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_endpoint(struct soap *soap, const char *endpoint) +{ register const char *s; + register size_t i, n; + soap->endpoint[0] = '\0'; + soap->host[0] = '\0'; + soap->path[0] = '/'; + soap->path[1] = '\0'; + soap->port = 80; + if (!endpoint || !*endpoint) + return; +#ifdef WITH_OPENSSL + if (!soap_tag_cmp(endpoint, "https:*")) + soap->port = 443; +#endif + strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint) - 1); + soap->endpoint[sizeof(soap->endpoint) - 1] = '\0'; + s = strchr(endpoint, ':'); + if (s && s[1] == '/' && s[2] == '/') + s += 3; + else + s = endpoint; + n = strlen(s); + if (n >= sizeof(soap->host)) + n = sizeof(soap->host) - 1; +#ifdef WITH_IPV6 + if (s[0] == '[') + { s++; + for (i = 0; i < n; i++) + { soap->host[i] = s[i]; + if (s[i] == ']') + { s++; + break; + } + } + } + else + { for (i = 0; i < n; i++) + { soap->host[i] = s[i]; + if (s[i] == '/' || s[i] == ':') + break; + } + } +#else + for (i = 0; i < n; i++) + { soap->host[i] = s[i]; + if (s[i] == '/' || s[i] == ':') + break; + } +#endif + soap->host[i] = '\0'; + if (s[i] == ':') + { soap->port = (int)atol(s + i + 1); + for (i++; i < n; i++) + if (s[i] == '/') + break; + } + if (s[i]) + { strncpy(soap->path, s + i, sizeof(soap->path)); + soap->path[sizeof(soap->path) - 1] = '\0'; + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_connect(struct soap *soap, const char *endpoint, const char *action) +{ return soap_connect_command(soap, SOAP_POST, endpoint, action); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_connect_command(struct soap *soap, int http_command, const char *endpoint, const char *action) +{ char host[sizeof(soap->host)]; + int port; + size_t count; + soap->error = SOAP_OK; + strcpy(host, soap->host); /* save to compare */ + port = soap->port; /* save to compare */ + soap_set_endpoint(soap, endpoint); +#ifndef WITH_LEANER + if (soap->fconnect) + { if ((soap->error = soap->fconnect(soap, endpoint, soap->host, soap->port))) + return soap->error; + } + else +#endif + if (soap->fopen && *soap->host) + { soap->status = http_command; + if (!soap->keep_alive || !soap_valid_socket(soap->socket) || strcmp(soap->host, host) || soap->port != port || !soap->fpoll || soap->fpoll(soap)) + { soap->keep_alive = 0; /* to force close */ + soap->omode &= ~SOAP_IO_UDP; /* to force close */ + soap_closesock(soap); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Connect/reconnect to host='%s' path='%s' port=%d\n", soap->host, soap->path, soap->port)); +#ifdef WITH_UDP + if (!strncmp(endpoint, "soap.udp:", 9)) + soap->omode |= SOAP_IO_UDP; +#endif + soap->socket = soap->fopen(soap, endpoint, soap->host, soap->port); + if (soap->error) + return soap->error; + soap->keep_alive = ((soap->omode & SOAP_IO_KEEPALIVE) != 0); + } + } + count = soap_count_attachments(soap); + if (soap_begin_send(soap)) + return soap->error; +#ifndef WITH_NOHTTP + soap->action = soap_strdup(soap, action); + if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML) && endpoint) + { unsigned int k = soap->mode; + soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB); + if ((k & SOAP_IO) != SOAP_IO_FLUSH) + soap->mode |= SOAP_IO_BUFFER; + if ((soap->error = soap->fpost(soap, endpoint, soap->host, soap->port, soap->path, action, count))) + return soap->error; +#ifndef WITH_LEANER + if ((k & SOAP_IO) == SOAP_IO_CHUNK) + { if (soap_flush(soap)) + return soap->error; + } +#endif + soap->mode = k; + } + if (http_command != SOAP_POST) + return soap_end_send(soap); +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_s2base64(struct soap *soap, const unsigned char *s, char *t, int n) +{ register int i; + register unsigned long m; + register char *p; + if (!t) + t = (char*)soap_malloc(soap, (n + 2) / 3 * 4 + 1); + if (!t) + { soap->error = SOAP_EOM; + return NULL; + } + p = t; + t[0] = '\0'; + if (!s) + return p; + for (; n > 2; n -= 3, s += 3) + { m = s[0]; + m = (m << 8) | s[1]; + m = (m << 8) | s[2]; + for (i = 4; i > 0; m >>= 6) + t[--i] = soap_base64o[m & 0x3F]; + t += 4; + } + t[0] = '\0'; + if (n > 0) + { m = 0; + for (i = 0; i < n; i++) + m = (m << 8) | *s++; + for (; i < 3; i++) + m <<= 8; + for (i++; i > 0; m >>= 6) + t[--i] = soap_base64o[m & 0x3F]; + for (i = 3; i > n; i--) + t[i] = '='; + t[4] = '\0'; + } + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_base642s(struct soap *soap, const char *s, char *t, size_t l, int *n) +{ register int i, j, c; + register unsigned long m; + register const char *p; + if (!s || !*s) + { if (n) + *n = 0; + if (soap->error) + return NULL; + return SOAP_NON_NULL; + } + if (!t) + { l = (strlen(s) + 3) / 4 * 3; + t = (char*)soap_malloc(soap, l); + } + if (!t) + { soap->error = SOAP_EOM; + return NULL; + } + p = t; + if (n) + *n = 0; + for (;;) + { for (i = 0; i < SOAP_BLKLEN; i++) + { m = 0; + j = 0; + while (j < 4) + { c = *s++; + if (c == '=' || !c) + { i *= 3; + switch (j) + { case 2: + *t++ = (char)((m >> 4) & 0xFF); + i++; + break; + case 3: + *t++ = (char)((m >> 10) & 0xFF); + *t++ = (char)((m >> 2) & 0xFF); + i += 2; + } + if (n) + *n += i; + return p; + } + c -= '+'; + if (c >= 0 && c <= 79) + { int b = soap_base64i[c]; + if (b >= 64) + { soap->error = SOAP_TYPE; + return NULL; + } + m = (m << 6) + b; + j++; + } + else if (!soap_blank(c)) + { soap->error = SOAP_TYPE; + return NULL; + } + } + *t++ = (char)((m >> 16) & 0xFF); + *t++ = (char)((m >> 8) & 0xFF); + *t++ = (char)(m & 0xFF); + if (l < 3) + { if (n) + *n += i; + return p; + } + l -= 3; + } + if (n) + *n += 3 * SOAP_BLKLEN; + } +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_s2hex(struct soap *soap, const unsigned char *s, char *t, int n) +{ register char *p; + if (!t) + t = (char*)soap_malloc(soap, 2 * n + 1); + if (!t) + { soap->error = SOAP_EOM; + return NULL; + } + p = t; + t[0] = '\0'; + if (s) + { for (; n > 0; n--) + { register int m = *s++; + *t++ = (char)((m >> 4) + (m > 159 ? 'a' - 10 : '0')); + m &= 0x0F; + *t++ = (char)(m + (m > 9 ? 'a' - 10 : '0')); + } + } + *t++ = '\0'; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_hex2s(struct soap *soap, const char *s, char *t, size_t l, int *n) +{ register const char *p; + if (!s || !*s) + { if (n) + *n = 0; + if (soap->error) + return NULL; + return SOAP_NON_NULL; + } + if (!t) + { l = strlen(s) / 2; + t = (char*)soap_malloc(soap, l); + } + if (!t) + { soap->error = SOAP_EOM; + return NULL; + } + p = t; + while (l) + { register int d1, d2; + d1 = *s++; + if (!d1) + break; + d2 = *s++; + if (!d2) + break; + *t++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'); + l--; + } + if (n) + *n = t - p; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_puthttphdr(struct soap *soap, int status, size_t count) +{ register const char *s = "text/xml; charset=utf-8"; + register int err = SOAP_OK; +#ifndef WITH_LEANER + register const char *r = NULL; +#endif + if (status == SOAP_FILE && soap->http_content) + s = soap->http_content; + else if (status == SOAP_HTML) + s = "text/html; charset=utf-8"; + else if (count || ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK)) + { if (soap->version == 2) + s = "application/soap+xml; charset=utf-8"; + } +#ifndef WITH_LEANER + if (soap->mode & (SOAP_ENC_DIME | SOAP_ENC_MTOM)) + { if (soap->mode & SOAP_ENC_MTOM) + { r = s; + s = "application/xop+xml; charset=utf-8"; + } + else + s = "application/dime"; + } + if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && soap->status != SOAP_GET && strlen(soap->mime.boundary) + strlen(soap->mime.start ? soap->mime.start : SOAP_STR_EOS) < sizeof(soap->tmpbuf) - 80) + { register const char *t = strchr(s, ';'); + sprintf(soap->tmpbuf, "multipart/related; boundary=\"%s\"; type=\"", soap->mime.boundary); + if (t) + strncat(soap->tmpbuf, s, t - s); + else + strcat(soap->tmpbuf, s); + if (soap->mime.start) + { strcat(soap->tmpbuf, "\"; start=\""); + strcat(soap->tmpbuf, soap->mime.start); + } + strcat(soap->tmpbuf, "\""); + if (r) + { strcat(soap->tmpbuf, "; start-info=\""); + strcat(soap->tmpbuf, r); + strcat(soap->tmpbuf, "\""); + } + s = soap->tmpbuf; + } +#endif + if (s && (err = soap->fposthdr(soap, "Content-Type", s))) + return err; +#ifdef WITH_ZLIB + if (soap->omode & SOAP_ENC_ZLIB) + { +#ifdef WITH_GZIP + err = soap->fposthdr(soap, "Content-Encoding", "gzip"); +#else + err = soap->fposthdr(soap, "Content-Encoding", "deflate"); +#endif + if (err) + return err; + } +#endif +#ifndef WITH_LEANER + if ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK) + err = soap->fposthdr(soap, "Transfer-Encoding", "chunked"); + else +#endif + if (s && soap->status != SOAP_GET) + { sprintf(soap->tmpbuf, "%lu", (unsigned long)count); + err = soap->fposthdr(soap, "Content-Length", soap->tmpbuf); + } + if (err) + return err; + return soap->fposthdr(soap, "Connection", soap->keep_alive ? "keep-alive" : "close"); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_get(struct soap *soap) +{ return SOAP_GET_METHOD; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_post(struct soap *soap, const char *endpoint, const char *host, int port, const char *path, const char *action, size_t count) +{ register const char *s; + register int err; + if (soap->status == SOAP_GET) + s = "GET"; + else + s = "POST"; +#ifdef PALM + if (!endpoint || (soap_tag_cmp(endpoint, "http:*") && soap_tag_cmp(endpoint, "https:*") && strncmp(endpoint, "httpg:", 6)) && strncmp(endpoint, "_beam:", 6) && strncmp(endpoint, "_local:", 7) && strncmp(endpoint, "_btobex:", 8)) +#else + if (!endpoint || (soap_tag_cmp(endpoint, "http:*") && soap_tag_cmp(endpoint, "https:*") && strncmp(endpoint, "httpg:", 6))) +#endif + return SOAP_OK; + if (strlen(endpoint) + strlen(soap->http_version) > sizeof(soap->tmpbuf) - 80) + return soap->error = SOAP_EOM; + if (soap->proxy_host && soap_tag_cmp(endpoint, "https:*")) + sprintf(soap->tmpbuf, "%s %s HTTP/%s", s, endpoint, soap->http_version); + else + sprintf(soap->tmpbuf, "%s /%s HTTP/%s", s, (*path == '/' ? path + 1 : path), soap->http_version); + if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return err; + if (port != 80) + sprintf(soap->tmpbuf, "%s:%d", host, port); + else + strcpy(soap->tmpbuf, host); + if ((err = soap->fposthdr(soap, "Host", soap->tmpbuf)) + || (err = soap->fposthdr(soap, "User-Agent", "gSOAP/2.7")) + || (err = soap_puthttphdr(soap, SOAP_OK, count))) + return err; +#ifdef WITH_ZLIB +#ifdef WITH_GZIP + if ((err = soap->fposthdr(soap, "Accept-Encoding", "gzip, deflate"))) +#else + if ((err = soap->fposthdr(soap, "Accept-Encoding", "deflate"))) +#endif + return err; +#endif +#ifndef WITH_LEAN + if (soap->userid && soap->passwd && strlen(soap->userid) + strlen(soap->passwd) < 761) + { sprintf(soap->tmpbuf + 262, "%s:%s", soap->userid, soap->passwd); + strcpy(soap->tmpbuf, "Basic "); + soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, strlen(soap->tmpbuf + 262)); + if ((err = soap->fposthdr(soap, "Authorization", soap->tmpbuf))) + return err; + } + if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761) + { sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd); + strcpy(soap->tmpbuf, "Basic "); + soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, strlen(soap->tmpbuf + 262)); + if ((err = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf))) + return err; + } +#endif +#ifdef WITH_COOKIES +#ifdef WITH_OPENSSL + if (soap_putcookies(soap, host, path, soap->ssl != NULL)) + return soap->error; +#else + if (soap_putcookies(soap, host, path, 0)) + return soap->error; +#endif +#endif + if (soap->version == 1 || (action && *action && strlen(action) < sizeof(soap->tmpbuf) - 2)) + { sprintf(soap->tmpbuf, "\"%s\"", action?action:""); + if ((err = soap->fposthdr(soap, "SOAPAction", soap->tmpbuf))) + return err; + } + return soap->fposthdr(soap, NULL, NULL); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_send_header(struct soap *soap, const char *s) +{ register const char *t; + do + { t = strchr(s, '\n'); /* disallow \n in HTTP headers */ + if (!t) + t = s + strlen(s); + if (soap_send_raw(soap, s, t - s)) + return soap->error; + s = t + 1; + } while (*t); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_post_header(struct soap *soap, const char *key, const char *val) +{ if (key) + { if (http_send_header(soap, key)) + return soap->error; + if (val && (soap_send_raw(soap, ": ", 2) || http_send_header(soap, val))) + return soap->error; + } + return soap_send_raw(soap, "\r\n", 2); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_response(struct soap *soap, int status, size_t count) +{ register int err; +#ifdef WMW_RPM_IO + if (soap->rpmreqid) + httpOutputEnable(soap->rpmreqid); +#endif + if (strlen(soap->http_version) > 4) + return soap->error = SOAP_EOM; + if (!status || status == SOAP_HTML || status == SOAP_FILE) + { const char *s; + if (count || ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK)) + s = "200 OK"; + else + s = "202 ACCEPTED"; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Status = %s\n", s)); +#ifdef WMW_RPM_IO + if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */ +#else + if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application */ +#endif + { sprintf(soap->tmpbuf, "HTTP/%s %s", soap->http_version, s); + if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return err; + } + else if ((err = soap->fposthdr(soap, "Status", s))) + return err; + } + else if (status >= 200 && status < 600) + { sprintf(soap->tmpbuf, "HTTP/%s %d %s", soap->http_version, status, http_error(soap, status)); + if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return err; +#ifndef WITH_LEAN + if (status == 401) + { sprintf(soap->tmpbuf, "Basic realm=\"%s\"", strlen(soap->authrealm) < sizeof(soap->tmpbuf) - 14 ? soap->authrealm : "gSOAP Web Service"); + if ((err = soap->fposthdr(soap, "WWW-Authenticate", soap->tmpbuf))) + return err; + } + else if ((status >= 301 && status <= 303) || status == 307) + { if ((err = soap->fposthdr(soap, "Location", soap->endpoint))) + return err; + } +#endif + } + else + { const char *s = *soap_faultcode(soap); + if (soap->version == 2 && !strcmp(s, "SOAP-ENV:Sender")) + s = "400 Bad Request"; + else + s = "500 Internal Server Error"; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error %s (status=%d)\n", s, status)); +#ifdef WMW_RPM_IO + if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */ +#else + if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application */ +#endif + { sprintf(soap->tmpbuf, "HTTP/%s %s", soap->http_version, s); + if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return err; + } + else if ((err = soap->fposthdr(soap, "Status", s))) /* CGI */ + return err; + } + if ((err = soap->fposthdr(soap, "Server", "gSOAP/2.7")) + || (err = soap_puthttphdr(soap, status, count))) + return err; +#ifdef WITH_COOKIES + if (soap_putsetcookies(soap)) + return soap->error; +#endif + return soap->fposthdr(soap, NULL, NULL); +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_response(struct soap *soap, int status) +{ register size_t count; + if (!(soap->omode & (SOAP_ENC_XML | SOAP_IO_STORE /* this tests for chunking too */)) + && (status == SOAP_HTML || status == SOAP_FILE)) + { soap->omode &= ~SOAP_IO; + soap->omode |= SOAP_IO_STORE; + } + soap->status = status; + count = soap_count_attachments(soap); + if (soap_begin_send(soap)) + return soap->error; +#ifndef WITH_NOHTTP + if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML)) + { register int n = soap->mode; + soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB); + if ((n & SOAP_IO) != SOAP_IO_FLUSH) + soap->mode |= SOAP_IO_BUFFER; + if ((soap->error = soap->fresponse(soap, status, count))) + return soap->error; +#ifndef WITH_LEANER + if ((n & SOAP_IO) == SOAP_IO_CHUNK) + { if (soap_flush(soap)) + return soap->error; + } +#endif + soap->mode = n; + } +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static const char* +soap_set_validation_fault(struct soap *soap, const char *s, const char *t) +{ if (*soap->tag) + sprintf(soap->msgbuf, "Validation constraint violation: %s%s in element <%s>", s, t?t:SOAP_STR_EOS, soap->tag); + else + sprintf(soap->msgbuf, "Validation constraint violation: %s%s", s, t?t:SOAP_STR_EOS); + return soap->msgbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_fault(struct soap *soap) +{ const char **c = soap_faultcode(soap); + const char **s = soap_faultstring(soap); + if (soap->fseterror) + soap->fseterror(soap, c, s); + if (!*c) + { if (soap->version == 2) + *c = "SOAP-ENV:Sender"; + else + *c = "SOAP-ENV:Client"; + } + if (*s) + return; + switch (soap->error) + { +#ifndef WITH_LEAN + case SOAP_CLI_FAULT: + *s = "Client fault"; + break; + case SOAP_SVR_FAULT: + *s = "Server fault"; + break; + case SOAP_TAG_MISMATCH: + *s = soap_set_validation_fault(soap, "tag name or namespace mismatch", NULL); + break; + case SOAP_TYPE: + *s = soap_set_validation_fault(soap, "data type mismatch ", soap->type); + break; + case SOAP_SYNTAX_ERROR: + *s = "Well-formedness violation"; + break; + case SOAP_NO_TAG: + *s = "No XML element tag"; + break; + case SOAP_MUSTUNDERSTAND: + *c = "SOAP-ENV:MustUnderstand"; + sprintf(soap->msgbuf, "The data in element '%s' must be understood but cannot be handled", soap->tag); + *s = soap->msgbuf; + break; + case SOAP_VERSIONMISMATCH: + *c = "SOAP-ENV:VersionMismatch"; + *s = "SOAP version mismatch or invalid SOAP message"; + break; + case SOAP_DATAENCODINGUNKNOWN: + *c = "SOAP-ENV:DataEncodingUnknown"; + *s = "Unsupported SOAP data encoding"; + break; + case SOAP_NAMESPACE: + *s = soap_set_validation_fault(soap, "namespace mismatch", NULL); + break; + case SOAP_USER_ERROR: + *s = "User error"; + break; + case SOAP_FATAL_ERROR: + *s = "Fatal error"; + break; + case SOAP_NO_METHOD: + sprintf(soap->msgbuf, "Method '%s' not implemented: method name or namespace not recognized", soap->tag); + *s = soap->msgbuf; + break; + case SOAP_NO_DATA: + *s = "Data required for operation"; + break; + case SOAP_GET_METHOD: + *s = "HTTP GET method not implemented"; + break; + case SOAP_EOM: + *s = "Out of memory"; + break; + case SOAP_MOE: + *s = "Memory overflow or corruption error"; + break; + case SOAP_IOB: + *s = "Array index out of bounds"; + break; + case SOAP_NULL: + *s = soap_set_validation_fault(soap, "nil not allowed", NULL); + break; + case SOAP_DUPLICATE_ID: + *s = soap_set_validation_fault(soap, "multiple definitions of id ", soap->id); + if (soap->version == 2) + *soap_faultsubcode(soap) = "SOAP-ENC:DuplicateID"; + break; + case SOAP_MISSING_ID: + *s = soap_set_validation_fault(soap, "missing id for ref ", soap->id); + if (soap->version == 2) + *soap_faultsubcode(soap) = "SOAP-ENC:MissingID"; + break; + case SOAP_HREF: + *s = soap_set_validation_fault(soap, "incompatible object ref ", soap->id); + break; + case SOAP_FAULT: + break; +#ifndef WITH_NOIO + case SOAP_UDP_ERROR: + *s = "Message too large for UDP packet"; + break; + case SOAP_TCP_ERROR: + *s = tcp_error(soap); + break; +#endif + case SOAP_HTTP_ERROR: + *s = "An HTTP processing error occurred"; + break; + case SOAP_SSL_ERROR: +#ifdef WITH_OPENSSL + *s = "SSL error"; +#else + *s = "OpenSSL not installed: recompile with -DWITH_OPENSSL"; +#endif + break; + case SOAP_PLUGIN_ERROR: + *s = "Plugin registry error"; + break; + case SOAP_DIME_ERROR: + *s = "DIME format error"; + break; + case SOAP_DIME_HREF: + *s = "DIME href to missing attachment"; + break; + case SOAP_DIME_MISMATCH: + *s = "DIME version/transmission error"; + break; + case SOAP_DIME_END: + *s = "End of DIME error"; + break; + case SOAP_MIME_ERROR: + *s = "MIME format error"; + break; + case SOAP_MIME_HREF: + *s = "MIME href to missing attachment"; + break; + case SOAP_MIME_END: + *s = "End of MIME error"; + break; + case SOAP_ZLIB_ERROR: +#ifdef WITH_ZLIB + sprintf(soap->msgbuf, "Zlib/gzip error: '%s'", soap->d_stream.msg?soap->d_stream.msg:""); + *s = soap->msgbuf; +#else + *s = "Zlib/gzip not installed for (de)compression: recompile with -DWITH_GZIP"; +#endif + break; + case SOAP_REQUIRED: + *s = soap_set_validation_fault(soap, "missing required attribute", NULL); + break; + case SOAP_PROHIBITED: + *s = soap_set_validation_fault(soap, "prohibited attribute present", NULL); + break; + case SOAP_OCCURS: + *s = soap_set_validation_fault(soap, "min/maxOccurs violation", NULL); + break; + case SOAP_LENGTH: + *s = soap_set_validation_fault(soap, "content length violation", NULL); + break; + case SOAP_FD_EXCEEDED: + *s = "Maximum number of open connections was reached"; + break; + case SOAP_STOP: + *s = "Stopped: no response sent"; + break; +#endif + case SOAP_EOF: +#ifndef WITH_NOIO + sprintf(soap->msgbuf, "End of file or no input: '%s'", soap_strerror(soap)); + *s = soap->msgbuf; + break; +#else + *s = "End of file or no input"; + break; +#endif + default: +#ifndef WITH_NOHTTP +#ifndef WITH_LEAN + if (soap->error > 200 && soap->error < 600) + { sprintf(soap->msgbuf, "HTTP Error: %d %s", soap->error, http_error(soap, soap->error)); + *s = soap->msgbuf; + } + else +#endif +#endif + { sprintf(soap->msgbuf, "Error %d", soap->error); + *s = soap->msgbuf; + } + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send_fault(struct soap *soap) +{ register int status = soap->error; + int r = 1; + if (status == SOAP_STOP) + return status; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Sending back fault struct for error code %d\n", soap->error)); + soap->keep_alive = 0; /* to terminate connection */ + soap_set_fault(soap); +#ifndef WITH_NOIO +#ifndef WITH_LEAN + if (soap_valid_socket(soap->socket)) + { struct timeval timeout; + fd_set rfd, sfd; + timeout.tv_sec = 0; + timeout.tv_usec = 0; + FD_ZERO(&rfd); + FD_ZERO(&sfd); + FD_SET((SOAP_SOCKET)soap->socket, &rfd); + FD_SET((SOAP_SOCKET)soap->socket, &sfd); + r = select((SOAP_SOCKET)(soap->socket + 1), &rfd, &sfd, NULL, &timeout); + if (r > 0) + { if (!FD_ISSET((SOAP_SOCKET)soap->socket, &sfd) + || (FD_ISSET((SOAP_SOCKET)soap->socket, &rfd) + && recv((SOAP_SOCKET)soap->socket, soap->tmpbuf, 1, MSG_PEEK) < 0)) + r = 0; + } + } +#endif +#endif + if ((status != SOAP_EOF || (!soap->recv_timeout && !soap->send_timeout)) && r > 0) + { soap->error = SOAP_OK; + soap_serializeheader(soap); + soap_serializefault(soap); + soap_begin_count(soap); + if (soap->mode & SOAP_IO_LENGTH) + { soap_envelope_begin_out(soap); + soap_putheader(soap); + soap_body_begin_out(soap); + soap_putfault(soap); + soap_body_end_out(soap); + soap_envelope_end_out(soap); + } + soap_end_count(soap); + if (soap_response(soap, status) + || soap_envelope_begin_out(soap) + || soap_putheader(soap) + || soap_body_begin_out(soap) + || soap_putfault(soap) + || soap_body_end_out(soap) + || soap_envelope_end_out(soap)) + return soap_closesock(soap); + soap_end_send(soap); + } + soap->error = status; + return soap_closesock(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv_fault(struct soap *soap) +{ register int status = soap->error; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Receiving SOAP Fault\n")); + soap->error = SOAP_OK; + if (soap_getfault(soap)) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Error: soap_get_soapfault() failed. Is this a SOAP message at all?\n")); + *soap_faultcode(soap) = (soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client"); + soap->error = status; + soap_set_fault(soap); + } + else + { register const char *s = *soap_faultcode(soap); + if (!soap_match_tag(soap, s, "SOAP-ENV:Server") || !soap_match_tag(soap, s, "SOAP-ENV:Receiver")) + status = SOAP_SVR_FAULT; + else if (!soap_match_tag(soap, s, "SOAP-ENV:Client") || !soap_match_tag(soap, s, "SOAP-ENV:Sender")) + status = SOAP_CLI_FAULT; + else if (!soap_match_tag(soap, s, "SOAP-ENV:MustUnderstand")) + status = SOAP_MUSTUNDERSTAND; + else if (!soap_match_tag(soap, s, "SOAP-ENV:VersionMismatch")) + status = SOAP_VERSIONMISMATCH; + else + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Fault code %s\n", s)); + status = SOAP_FAULT; + } + if (soap_body_end_in(soap) + || soap_envelope_end_in(soap) + || soap_end_recv(soap)) + return soap_closesock(soap); + soap->error = status; + } + return soap_closesock(soap); +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send_empty_response(struct soap *soap, int status) +{ register soap_mode m = soap->omode; + soap->count = 0; + if ((m & SOAP_IO) == SOAP_IO_CHUNK) + { soap->omode &= ~SOAP_IO_CHUNK; + soap->omode |= SOAP_IO_BUFFER; + } + if (soap_response(soap, status) || soap_end_send(soap)) + { soap->omode = m; + return soap_closesock(soap); + } + soap->omode = m; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv_empty_response(struct soap *soap) +{ if (soap_begin_recv(soap) || soap_end_recv(soap)) + { if (soap->error != 202) + return soap_closesock(soap); + soap->error = SOAP_OK; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static const char* +soap_strerror(struct soap *soap) +{ register int err = soap->errnum; + if (err) + { +#ifndef WIN32 + return strerror(err); +#else +#ifndef UNDER_CE + DWORD len; + *soap->msgbuf = '\0'; + len = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)soap->msgbuf, (DWORD)sizeof(soap->msgbuf), NULL); +#else + DWORD i, len; + *soap->msgbuf = '\0'; + len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0, (LPTSTR)soap->msgbuf, (DWORD)(sizeof(soap->msgbuf)/sizeof(TCHAR)), NULL); + for (i = 0; i <= len; i++) + { if (((TCHAR*)soap->msgbuf)[i] < 0x80) + soap->msgbuf[i] = (char)((TCHAR*)soap->msgbuf)[i]; + else + soap->msgbuf[i] = '?'; + } +#endif + return soap->msgbuf; +#endif + } + return "Operation interrupted or timed out"; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +static int +soap_set_error(struct soap *soap, const char *faultcode, const char *faultsubcode, const char *faultstring, const char *faultdetail, int soaperror) +{ *soap_faultcode(soap) = faultcode; + if (faultsubcode) + *soap_faultsubcode(soap) = faultsubcode; + *soap_faultstring(soap) = faultstring; + if (faultdetail && *faultdetail) + { register const char **s = soap_faultdetail(soap); + if (s) + *s = faultdetail; + } + return soap->error = soaperror; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_sender_error(struct soap *soap, const char *faultstring, const char *faultdetail, int soaperror) +{ return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", NULL, faultstring, faultdetail, soaperror); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_receiver_error(struct soap *soap, const char *faultstring, const char *faultdetail, int soaperror) +{ return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", NULL, faultstring, faultdetail, soaperror); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +static int +soap_copy_fault(struct soap *soap, const char *faultcode, const char *faultsubcode, const char *faultstring, const char *faultdetail) +{ char *r = NULL, *s = NULL, *t = NULL; + if (faultsubcode) + r = soap_strdup(soap, faultsubcode); + if (faultstring) + s = soap_strdup(soap, faultstring); + if (faultdetail) + t = soap_strdup(soap, faultdetail); + return soap_set_error(soap, faultcode, r, s, t, SOAP_FAULT); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_sender_fault(struct soap *soap, const char *faultstring, const char *faultdetail) +{ return soap_sender_fault_subcode(soap, NULL, faultstring, faultdetail); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_sender_fault_subcode(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail) +{ return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", faultsubcode, faultstring, faultdetail); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_receiver_fault(struct soap *soap, const char *faultstring, const char *faultdetail) +{ return soap_receiver_fault_subcode(soap, NULL, faultstring, faultdetail); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_receiver_fault_subcode(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail) +{ return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", faultsubcode, faultstring, faultdetail); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +#ifndef WITH_NOSTDLIB +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_print_fault(struct soap *soap, FILE *fd) +{ if (soap_check_state(soap)) + fprintf(fd, "Error: soap struct not initialized\n"); + else if (soap->error) + { const char *c, *v = NULL, *s, **d; + d = soap_faultcode(soap); + if (!*d) + soap_set_fault(soap); + c = *d; + if (soap->version == 2) + v = *soap_faultsubcode(soap); + s = *soap_faultstring(soap); + d = soap_faultdetail(soap); + fprintf(fd, "%s%d fault: %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, c, v ? v : "no subcode", s ? s : "[no reason]", d && *d ? *d : "[no detail]"); + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +#ifndef WITH_NOSTDLIB +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_print_fault_location(struct soap *soap, FILE *fd) +{ +#ifndef WITH_LEAN + int i, j, c1, c2; + if (soap->error && soap->bufidx <= soap->buflen && soap->buflen > 0 && soap->buflen <= SOAP_BUFLEN) + { i = (int)soap->bufidx - 1; + if (i <= 0) + i = 0; + c1 = soap->buf[i]; + soap->buf[i] = '\0'; + if ((int)soap->buflen >= i + 1024) + j = i + 1023; + else + j = (int)soap->buflen - 1; + c2 = soap->buf[j]; + soap->buf[j] = '\0'; + fprintf(fd, "%s%c\n\n", soap->buf, c1); + if (soap->bufidx < soap->buflen) + fprintf(fd, "%s\n", soap->buf + soap->bufidx); + soap->buf[i] = c1; + soap->buf[j] = c2; + } +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_register_plugin_arg(struct soap *soap, int (*fcreate)(struct soap*, struct soap_plugin*, void*), void *arg) +{ register struct soap_plugin *p; + register int r; + if (!(p = (struct soap_plugin*)SOAP_MALLOC(soap, sizeof(struct soap_plugin)))) + return soap->error = SOAP_EOM; + p->id = NULL; + p->data = NULL; + p->fcopy = NULL; + p->fdelete = NULL; + r = fcreate(soap, p, arg); + if (!r && p->fdelete) + { p->next = soap->plugins; + soap->plugins = p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Registered '%s' plugin\n", p->id)); + return SOAP_OK; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not register plugin '%s': plugin returned error %d (or fdelete callback not set)\n", p->id?p->id:"?", r)); + SOAP_FREE(soap, p); + return r; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static void * +fplugin(struct soap *soap, const char *id) +{ register struct soap_plugin *p; + for (p = soap->plugins; p; p = p->next) + if (p->id == id || !strcmp(p->id, id)) + return p->data; + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void * +SOAP_FMAC2 +soap_lookup_plugin(struct soap *soap, const char *id) +{ return soap->fplugin(soap, id); +} +#endif + +/******************************************************************************/ +#ifdef __cplusplus +} +#endif + +/******************************************************************************\ + * + * C++ soap struct methods + * +\******************************************************************************/ + +#ifdef __cplusplus +#ifndef WITH_LEAN +soap::soap() +{ soap_init(this); +} +#endif +#endif + +/******************************************************************************/ +#ifdef __cplusplus +#ifndef WITH_LEAN +soap::soap(soap_mode m) +{ soap_init1(this, m); +} +#endif +#endif + +/******************************************************************************/ +#ifdef __cplusplus +#ifndef WITH_LEAN +soap::soap(soap_mode im, soap_mode om) +{ soap_init2(this, im, om); +} +#endif +#endif + +/******************************************************************************/ +#ifdef __cplusplus +#ifndef WITH_LEAN +soap::soap(struct soap& soap) +{ soap_copy_context(this, &soap); +} +#endif +#endif + +/******************************************************************************/ +#ifdef __cplusplus +#ifndef WITH_LEAN +soap::~soap() +{ soap_destroy(this); + soap_end(this); + soap_done(this); +} +#endif +#endif + +/******************************************************************************/ diff --git a/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.9b.h b/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.9b.h new file mode 100644 index 0000000..2a8928b --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.9b.h @@ -0,0 +1,2166 @@ +/* + +stdsoap2.h 2.7.9b + +gSOAP runtime + +gSOAP XML Web services tools +Copyright (C) 2000-2007, Robert van Engelen, Genivia Inc., All Rights Reserved. +This part of the software is released under one of the following licenses: +GPL, the gSOAP public license, or Genivia's license for commercial use. +-------------------------------------------------------------------------------- +Contributors: + +Wind River Systems, Inc., for the following additions (marked WR[...]): + - vxWorks compatible +-------------------------------------------------------------------------------- +gSOAP public license. + +The contents of this file are subject to the gSOAP Public License Version 1.3 +(the "License"); you may not use this file except in compliance with the +License. You may obtain a copy of the License at +http://www.cs.fsu.edu/~engelen/soaplicense.html +Software distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +for the specific language governing rights and limitations under the License. + +The Initial Developer of the Original Code is Robert A. van Engelen. +Copyright (C) 2000-2007, Robert van Engelen, Genivia Inc., All Rights Reserved. +-------------------------------------------------------------------------------- +GPL license. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA + +Author contact information: +engelen@genivia.com / engelen@acm.org +-------------------------------------------------------------------------------- +A commercial use license is available from Genivia, Inc., contact@genivia.com +-------------------------------------------------------------------------------- +*/ + +#ifdef WITH_SOAPDEFS_H +# include "soapdefs.h" /* include user-defined stuff */ +#endif + +#ifndef _THREAD_SAFE +# define _THREAD_SAFE +#endif + +#ifndef OPENSERVER +# ifndef _REENTRANT +# define _REENTRANT +# endif +#endif + +#ifndef SOAP_FMAC1 /* stdsoap2.h declaration macro */ +# define SOAP_FMAC1 +#endif + +#ifndef SOAP_FMAC2 /* stdsoap2.h declaration macro */ +# define SOAP_FMAC2 +#endif + +#ifndef SOAP_FMAC3 /* (de)serializer declaration macro */ +# define SOAP_FMAC3 +#endif + +#ifndef SOAP_FMAC3S /* string converter for (de)serializer declaration macro */ +# define SOAP_FMAC3S SOAP_FMAC3 +#endif + +#ifndef SOAP_FMAC4 /* (de)serializer declaration macro */ +# define SOAP_FMAC4 +#endif + +#ifndef SOAP_FMAC4S /* string converter for (de)serializer declaration macro */ +# define SOAP_FMAC4S SOAP_FMAC4 +#endif + +#ifndef SOAP_FMAC5 /* stub/skeleton declaration macro */ +# define SOAP_FMAC5 +#endif + +#ifndef SOAP_FMAC6 /* stub/skeleton declaration macro */ +# define SOAP_FMAC6 +#endif + +#ifndef SOAP_CMAC /* class declaration macro */ +# define SOAP_CMAC +#endif + +#ifndef SOAP_NMAC /* namespace table declaration macro */ +# define SOAP_NMAC +#endif + +#ifndef SOAP_SOURCE_STAMP +# define SOAP_SOURCE_STAMP(str) +#endif + +/* gSOAP 2.7.4 and higher: fast look-aside buffering is stable */ +#ifndef WITH_FAST +# define WITH_FAST +#endif + +#ifdef WITH_LEANER +# ifndef WITH_LEAN +# define WITH_LEAN +# endif +#endif + +#ifdef WITH_LEAN +# ifdef WITH_COOKIES +# error "Cannot build WITH_LEAN code WITH_COOKIES enabled" +# endif +#endif + +#ifndef STDSOAP_H +#define STDSOAP_H + +#if defined(__vxworks) || defined(__VXWORKS__) +# define VXWORKS +#endif + +#ifdef _WIN32 +# ifndef WIN32 +# define WIN32 +# endif +#endif + +#ifdef _WIN32_WCE +# ifndef UNDER_CE +# define UNDER_CE _WIN32_WCE +# endif +#endif + +#ifdef UNDER_CE +# ifndef WIN32 +# define WIN32 +# endif +#endif + +#ifdef __BORLANDC__ +# ifdef __WIN32__ +# ifndef WIN32 +# define WIN32 +# endif +# endif +#endif + +#ifdef __CYGWIN__ +# ifndef CYGWIN +# define CYGWIN +# endif +#endif + +#ifdef __SYMBIAN32__ +# define SYMBIAN +# undef WIN32 +#endif + +#if defined(__palmos__) || defined(PALM_GCC) || defined(__PALMOS_TRAPS__) +# ifndef PALM +# define PALM +# endif +#endif + +#if defined(__hpux) +# ifndef HP_UX +# define HP_UX +# endif +#endif + +#if defined(__alpha) && !defined(__VMS) +# ifndef TRU64 +# define TRU64 +# endif +#endif + +#ifdef __MVS__ +# ifndef OS390 +# define OS390 +# endif +#endif + +#ifdef HAVE_CONFIG_H +# include "config.h" +# ifdef WITH_OPENSSL +# ifndef HAVE_OPENSSL_SSL_H +# undef WITH_OPENSSL +# endif +# endif +#else +# if defined(UNDER_CE) +# define WITH_LEAN +# define HAVE_SSCANF +# elif defined(WIN32) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# define SOAP_LONG_FORMAT "%I64d" +# define SOAP_ULONG_FORMAT "%I64u" +# elif defined(CYGWIN) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(__APPLE__) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_TIMEGM +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(_AIXVERSION_431) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(HP_UX) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(FREEBSD) || defined(__FreeBSD__) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_STRTOLL +# define HAVE_STRTOULL +# define HAVE_GETTIMEOFDAY +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# define SOAP_LONG_FORMAT "%qd" +# define SOAP_ULONG_FORMAT "%qu" +# elif defined(__VMS) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(__GLIBC__) || defined(__GNU__) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_STRTOLL +# define HAVE_STRTOULL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_TIMEGM +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# define HAVE_ISNAN +# elif defined(TRU64) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_GETTIMEOFDAY +# define HAVE_SYS_TIMEB_H +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define __USE_STD_IOSTREAM +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# define SOAP_LONG_FORMAT "%ld" +# define SOAP_ULONG_FORMAT "%lu" +# elif defined(MAC_CARBON) +# define WITH_NOIO +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GETHOSTBYNAME_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(PALM) +# define WITH_LEAN +# define HAVE_STRTOD /* strtod() is defined in palmFunctions.h */ +# include /* Needs to be included before unix headers */ +# include +# define IGNORE_STDIO_STUBS +# include +# define O_NONBLOCK FNONBIO +# include +# include "palmFunctions.h" +# elif defined(SYMBIAN) +# define WITH_LEAN +# define WITH_NONAMESPACES +# define HAVE_STRTOD /* use STRTOD since sscanf doesn't seem to work */ +# include +# include +# elif defined(VXWORKS) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_PGMTIME_R +# define HAVE_PLOCALTIME_R +# define HAVE_MKTIME +# elif defined(OS390) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(AS400) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(__QNX__) || defined(QNX) +/* QNX does not have a working version of strtof */ +# undef HAVE_STRTOF +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GETHOSTBYNAME_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# define LONG64 long +# define ULONG64 unsigned LONG64 +# define SOAP_LONG_FORMAT "%ld" +# define SOAP_ULONG_FORMAT "%lu" +# else +/* Default asumptions on supported functions */ +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GETHOSTBYNAME_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# endif +#endif + +#ifndef SOAP_LONG_FORMAT +# define SOAP_LONG_FORMAT "%lld" /* printf format for 64 bit ints */ +#endif + +#ifndef SOAP_ULONG_FORMAT +# define SOAP_ULONG_FORMAT "%llu" /* printf format for unsigned 64 bit ints */ +#endif + +#ifndef WITH_NOSTDLIB +# include +# ifndef PALM +# include +# include +# endif +# include +# include +#endif + +#if defined(__cplusplus) && !defined(WITH_LEAN) +# include +# include +#endif + +#ifdef WITH_NOHTTP +# ifndef WITH_NOIO +# define WITH_NOIO +# undef WITH_COOKIES +# endif +#endif + +#ifndef UNDER_CE +# ifndef PALM +# ifndef WITH_NOIO +# include +# include +# endif +# ifndef WITH_LEAN +# ifdef HAVE_SYS_TIMEB_H +# include /* for ftime() */ +# endif +# include +# endif +# endif +#endif + +#ifdef OPENSERVER +# include +# include +# include + extern int h_errno; +#endif + +#ifndef WITH_NOIO +# ifndef WIN32 +# ifndef PALM +# include +# ifdef VXWORKS +# include +# include +# endif +# ifndef VXWORKS +# ifndef SYMBIAN +# include +# endif +# endif +# ifdef SUN_OS +# include /* SUN */ +# include /* SUN < 2.8 (?) */ +# endif +# ifdef VXWORKS +# ifdef _WRS_KERNEL +# include +# endif +# else +# include +# endif +# include +# ifdef OS390 +# include +# else +# include /* TCP_NODELAY */ +# endif +# include +# endif +# endif +#endif + +#ifdef WITH_FASTCGI +# include +#endif + +#ifdef WITH_OPENSSL +# define OPENSSL_NO_KRB5 +# include +# include +# include +# include +# include +# ifndef ALLOW_OLD_VERSIONS +# if (OPENSSL_VERSION_NUMBER < 0x00905100L) +# error "Must use OpenSSL 0.9.6 or later" +# endif +# endif +#endif + +#ifdef WITH_GZIP +# ifndef WITH_ZLIB +# define WITH_ZLIB +# endif +#endif + +#ifdef WITH_CASEINSENSITIVETAGS +# define SOAP_STRCMP soap_tag_cmp /* case insensitve XML element/attribute names */ +#else +# define SOAP_STRCMP strcmp /* case sensitive XML element/attribute names */ +#endif + +#ifdef WITH_ZLIB +# include +#endif + +#ifndef WITH_NOSTDLIB +# ifndef PALM +# include /* for isnan() */ +# endif +#endif + +/* #define DEBUG */ /* Uncomment to debug sending (in file SENT.log) receiving (in file RECV.log) and messages (in file TEST.log) */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef WIN32 +# ifndef UNDER_CE +# include +# include +# endif +# include +/* # include */ /* Alternative: use winsock2 (not available with eVC) */ +# ifdef WITH_IPV6 +# include +# include +# endif +#else +# ifdef VXWORKS +# include +# include +# include +# endif +# ifndef WITH_NOIO +# ifndef PALM +# include +# include +# include +# include +# endif +# endif +#endif + +/* Portability: define SOAP_SOCKLEN_T */ +#if defined(_AIX) +# define SOAP_SOCKLEN_T socklen_t +#elif defined(SOCKLEN_T) +# define SOAP_SOCKLEN_T SOCKLEN_T +#elif defined(__socklen_t_defined) || defined(_SOCKLEN_T) || defined(CYGWIN) || defined(FREEBSD) || defined(__FreeBSD__) || defined(__QNX__) || defined(QNX) +# define SOAP_SOCKLEN_T socklen_t +#elif defined(IRIX) || defined(WIN32) || defined(__APPLE__) || defined(HP_UX) || defined(SUN_OS) || defined(OPENSERVER) || defined(TRU64) || defined(VXWORKS) +# define SOAP_SOCKLEN_T int +#else +# define SOAP_SOCKLEN_T size_t +#endif + +#ifndef SOAP_SOCKET +# ifdef WIN32 +# define SOAP_SOCKET SOCKET +# define soap_closesocket(n) closesocket(n) +# else +# define SOAP_SOCKET int +# define soap_closesocket(n) close(n) +# endif +#endif + +#define SOAP_INVALID_SOCKET (-1) +#define soap_valid_socket(n) ((n) != SOAP_INVALID_SOCKET) + +#ifndef FD_SETSIZE +# define FD_SETSIZE (1024) +#endif + +#if defined(SYMBIAN) +# define LONG64 long +# define ULONG64 unsigned LONG64 +#elif !defined(WIN32) || defined(CYGWIN) || defined(__GLIBC__) || defined(__GNU__) +# ifndef LONG64 +# define LONG64 long long +# define ULONG64 unsigned LONG64 +# endif +#elif defined(UNDER_CE) +# define LONG64 __int64 +# define ULONG64 unsigned LONG64 +#elif defined(__BORLANDC__) +# define LONG64 __int64 +# define ULONG64 unsigned LONG64 +#endif + +#if defined(WIN32) && !defined(CYGWIN) +# define soap_int32 __int32 +#elif defined(SYMBIAN) +# define soap_int32 long +#elif defined(PALM) +# define soap_int32 Int32 +#else +# define soap_int32 int32_t +#endif + +#ifdef WIN32 +# define SOAP_ERANGE ERANGE +# define SOAP_EINTR WSAEINTR +# define SOAP_EAGAIN WSAEWOULDBLOCK +# define SOAP_EWOULDBLOCK WSAEWOULDBLOCK +# define SOAP_EINPROGRESS WSAEINPROGRESS +#else +# define SOAP_ERANGE ERANGE +# define SOAP_EINTR EINTR +# define SOAP_EAGAIN EAGAIN +# ifdef SYMBIAN +# define SOAP_EWOULDBLOCK 9898 +# define SOAP_EINPROGRESS 9899 +# else +# define SOAP_EWOULDBLOCK EWOULDBLOCK +# define SOAP_EINPROGRESS EINPROGRESS +# endif +#endif + +#ifdef WIN32 +# ifdef UNDER_CE +# define soap_errno GetLastError() +# define soap_socket_errno(s) GetLastError() +# define soap_reset_errno SetLastError(0) +# else +# define soap_errno GetLastError() +# define soap_socket_errno(s) WSAGetLastError() +# define soap_reset_errno SetLastError(0) +# endif +#else +# ifndef WITH_NOIO +# define soap_errno errno +# define soap_socket_errno(s) errno +# define soap_reset_errno (errno = 0) +# else +# define soap_errno 0 +# define soap_socket_errno(s) 0 +# define soap_reset_errno +# endif +#endif + +#ifndef SOAP_BUFLEN +# ifdef WITH_UDP +# define SOAP_BUFLEN (65536) /* max UDP packet size */ +# else +# ifndef WITH_LEAN +# define SOAP_BUFLEN (65536) /* buffer length for socket packets, also used by gethostbyname_r so don't make this too small */ +# else +# define SOAP_BUFLEN (2048) +# endif +# endif +#endif +#ifndef SOAP_LABLEN +# define SOAP_LABLEN (256) /* initial look-aside buffer length */ +#endif +#ifndef SOAP_PTRBLK +# define SOAP_PTRBLK (32) /* block allocation for pointer hash table chains */ +#endif +#ifndef SOAP_PTRHASH +# ifndef WITH_LEAN +# define SOAP_PTRHASH (1024) /* size of pointer analysis hash table (must be power of 2) */ +# else +# define SOAP_PTRHASH (32) +# endif +#endif +#ifndef SOAP_IDHASH +# ifndef WITH_LEAN +# define SOAP_IDHASH (1999) /* prime size of hash table for parsed id/ref */ +# else +# define SOAP_IDHASH (19) /* 19, 199 */ +# endif +#endif +#ifndef SOAP_BLKLEN +# ifndef WITH_LEAN +# define SOAP_BLKLEN (256) /* size of blocks to collect long strings and XML attributes */ +# else +# define SOAP_BLKLEN (32) +# endif +#endif +#ifndef SOAP_TAGLEN +# ifndef WITH_LEAN +# define SOAP_TAGLEN (1024) /* maximum length of XML element tag/attribute name or host/path name + 1 */ +# else +# define SOAP_TAGLEN (64) +# endif +#endif +#ifndef SOAP_HDRLEN +# ifndef WITH_LEAN +# define SOAP_HDRLEN (8192) /* maximum length of HTTP header line (must be >4096 to read cookies) */ +# else +# define SOAP_HDRLEN (1024) +# endif +#endif +#ifndef SOAP_MAXDIMS +# ifndef WITH_LEAN +# define SOAP_MAXDIMS (16) /* maximum array dimensions (array nestings) must be less than 64 to protect soap->tmpbuf */ +# else +# define SOAP_MAXDIMS (4) +# endif +#endif + +#ifndef SOAP_MAXLOGS +# define SOAP_MAXLOGS (3) /* max number of debug logs per struct soap environment */ +# define SOAP_INDEX_RECV (0) +# define SOAP_INDEX_SENT (1) +# define SOAP_INDEX_TEST (2) +#endif + +#ifndef SOAP_MAXKEEPALIVE +# define SOAP_MAXKEEPALIVE (100) /* max iterations to keep server connection alive */ +#endif + +#ifndef SOAP_MAXARRAYSIZE +# define SOAP_MAXARRAYSIZE (100000) /* "trusted" max size of inbound SOAP array for compound array allocation */ +#endif + +#ifdef VXWORKS +# ifdef __INCmathh +# include +# ifndef HAVE_ISNAN +# define HAVE_ISNAN +# endif +# define soap_isnan(num) isNan(num) +# endif +#endif + +#ifdef WIN32 +# include +# ifndef HAVE_ISNAN +# define HAVE_ISNAN +# endif +# define soap_isnan(num) _isnan(num) +#endif + +#ifdef SUN_OS +# define HAVE_ISNAN +#endif + +#ifdef __APPLE__ +# ifdef __cplusplus +# ifndef isnan +extern "C" int isnan(double); +# endif +# endif +# define HAVE_ISNAN +#endif + +#if !defined(HAVE_ISNAN) && (defined(_MATH_H) || defined(_MATH_INCLUDED)) +# define HAVE_ISNAN +#endif + +extern const struct soap_double_nan { unsigned int n1, n2; } soap_double_nan; + +#ifdef VXWORKS +# ifndef FLT_MAX +# define FLT_MAX _ARCH_FLT_MAX +# endif +# ifndef DBL_MAX +# define DBL_MAX _ARCH_DBL_MAX +# endif +#endif + +#ifndef FLT_NAN +# define FLT_NAN (*(float*)(void*)&soap_double_nan) +#endif + +#ifndef FLT_PINFTY +# if defined(FLT_MAX) +# define FLT_PINFTY FLT_MAX +# elif defined(HUGE_VALF) +# define FLT_PINFTY (float)HUGE_VALF +# elif defined(HUGE_VAL) +# define FLT_PINFTY (float)HUGE_VAL +# elif defined(FLOAT_MAX) +# define FLT_PINFTY FLOAT_MAX +# else +# define FLT_PINFTY (3.40282347e+38F) +# endif +#endif + +#ifndef FLT_NINFTY +# define FLT_NINFTY (-FLT_PINFTY) +#endif + +#ifndef DBL_NAN +# define DBL_NAN (*(double*)(void*)&soap_double_nan) +#endif + +#ifndef DBL_PINFTY +# if defined(DBL_MAX) +# define DBL_PINFTY DBL_MAX +# elif defined(HUGE_VALF) +# define DBL_PINFTY (double)HUGE_VALF +# elif defined(HUGE_VAL) +# define DBL_PINFTY (double)HUGE_VAL +# elif defined(DOUBLE_MAX) +# define DBL_PINFTY DOUBLE_MAX +# else +# define DBL_PINFTY (1.7976931348623157e+308) +# endif +#endif + +#ifndef DBL_NINFTY +# define DBL_NINFTY (-DBL_PINFTY) +#endif + +#ifndef soap_isnan +# ifdef HAVE_ISNAN +# define soap_isnan(n) isnan(n) +# else +# define soap_isnan(n) (0) +# endif +#endif + +#define soap_ispinfd(n) ((n) >= DBL_PINFTY) +#define soap_ispinff(n) ((n) >= FLT_PINFTY) +#define soap_isninfd(n) ((n) <= DBL_NINFTY) +#define soap_isninff(n) ((n) <= FLT_NINFTY) + +/* gSOAP error codes */ + +#define SOAP_EOF EOF +#define SOAP_ERR EOF +#define SOAP_OK 0 +#define SOAP_CLI_FAULT 1 +#define SOAP_SVR_FAULT 2 +#define SOAP_TAG_MISMATCH 3 +#define SOAP_TYPE 4 +#define SOAP_SYNTAX_ERROR 5 +#define SOAP_NO_TAG 6 +#define SOAP_IOB 7 +#define SOAP_MUSTUNDERSTAND 8 +#define SOAP_NAMESPACE 9 +#define SOAP_USER_ERROR 10 +#define SOAP_FATAL_ERROR 11 +#define SOAP_FAULT 12 +#define SOAP_NO_METHOD 13 +#define SOAP_NO_DATA 14 +#define SOAP_GET_METHOD 15 +#define SOAP_EOM 16 +#define SOAP_MOE 17 +#define SOAP_NULL 18 +#define SOAP_DUPLICATE_ID 19 +#define SOAP_MISSING_ID 20 +#define SOAP_HREF 21 +#define SOAP_UDP_ERROR 22 +#define SOAP_TCP_ERROR 23 +#define SOAP_HTTP_ERROR 24 +#define SOAP_SSL_ERROR 25 +#define SOAP_ZLIB_ERROR 26 +#define SOAP_DIME_ERROR 27 +#define SOAP_DIME_HREF 28 +#define SOAP_DIME_MISMATCH 29 +#define SOAP_DIME_END 30 +#define SOAP_MIME_ERROR 31 +#define SOAP_MIME_HREF 32 +#define SOAP_MIME_END 33 +#define SOAP_VERSIONMISMATCH 34 +#define SOAP_PLUGIN_ERROR 35 +#define SOAP_DATAENCODINGUNKNOWN 36 +#define SOAP_REQUIRED 37 +#define SOAP_PROHIBITED 38 +#define SOAP_OCCURS 39 +#define SOAP_LENGTH 40 +#define SOAP_FD_EXCEEDED 41 + +#define soap_xml_error_check(e) ((e) == SOAP_TAG_MISMATCH || (e) == SOAP_TAG_END || (e) == SOAP_SYNTAX_ERROR || (e) == SOAP_NAMESPACE || (e) == SOAP_DUPLICATE_ID || (e) == SOAP_MISSING_ID || (e) == SOAP_REQUIRED || (e) == SOAP_PROHIBITED || (e) == SOAP_OCCURS || (e) == SOAP_LENGTH || (e) == SOAP_NULL || (e) == SOAP_HREF) +#define soap_soap_error_check(e) ((e) == SOAP_CLI_FAULT || (e) == SOAP_SVR_FAULT || (e) == SOAP_VERSIONMISMATCH || (e) == SOAP_MUSTUNDERSTAND || (e) == SOAP_FAULT || (e) == SOAP_NO_METHOD) +#define soap_tcp_error_check(e) ((e) == SOAP_EOF || (e) == SOAP_TCP_ERROR) +#define soap_ssl_error_check(e) ((e) == SOAP_SSL_ERROR) +#define soap_zlib_error_check(e) ((e) == SOAP_ZLIB_ERROR) +#define soap_http_error_check(e) ((e) == SOAP_HTTP_ERROR || (e) == SOAP_GET_METHOD || (e) == SOAP_NO_DATA || ((e) >= 100 && (e) < 600)) + +/* gSOAP HTTP response status codes 100 to 599 are reserved */ + +/* Codes 600 to 999 are user definable */ + +/* Exceptional gSOAP HTTP response status codes >= 1000 */ + +#define SOAP_STOP 1000 /* No HTTP response */ +#define SOAP_FORM 1001 /* Form request/response */ +#define SOAP_HTML 1002 /* Custom HTML response */ +#define SOAP_FILE 1003 /* Custom file-based response */ + +/* gSOAP HTTP method codes */ + +#define SOAP_POST 2000 +#define SOAP_GET 2001 + +/* gSOAP DIME */ + +#define SOAP_DIME_CF 0x01 +#define SOAP_DIME_ME 0x02 +#define SOAP_DIME_MB 0x04 +#define SOAP_DIME_VERSION 0x08 /* DIME version 1 */ +#define SOAP_DIME_MEDIA 0x10 +#define SOAP_DIME_ABSURI 0x20 + +/* gSOAP ZLIB */ + +#define SOAP_ZLIB_NONE 0x00 +#define SOAP_ZLIB_DEFLATE 0x01 +#define SOAP_ZLIB_INFLATE 0x02 +#define SOAP_ZLIB_GZIP 0x02 + +/* gSOAP transport, connection, and content encoding modes */ + +typedef soap_int32 soap_mode; + +#define SOAP_IO 0x00000003 /* IO mask */ +#define SOAP_IO_FLUSH 0x00000000 /* flush output immediately, no buffering */ +#define SOAP_IO_BUFFER 0x00000001 /* buffer output in packets of size SOAP_BUFLEN */ +#define SOAP_IO_STORE 0x00000002 /* store entire output to determine length for transport */ +#define SOAP_IO_CHUNK 0x00000003 /* use HTTP chunked transfer AND buffer packets */ + +#define SOAP_IO_UDP 0x00000004 /* TCP or UDP */ + +#define SOAP_IO_LENGTH 0x00000008 /* calc message length (internal) */ +#define SOAP_IO_KEEPALIVE 0x00000010 /* keep connection alive */ + +#define SOAP_ENC_LATIN 0x00000020 /* accept iso-8859-1 encoding */ +#define SOAP_ENC_XML 0x00000040 /* plain XML encoding, no HTTP header */ +#define SOAP_ENC_DIME 0x00000080 +#define SOAP_ENC_MIME 0x00000100 +#define SOAP_ENC_MTOM 0x00000200 +#define SOAP_ENC_ZLIB 0x00000400 +#define SOAP_ENC_SSL 0x00000800 + +#define SOAP_ENC 0x00000FFF /* IO and ENC mask */ + +#define SOAP_XML_STRICT 0x00001000 /* apply strict validation */ +#define SOAP_XML_INDENT 0x00002000 /* emit indented XML */ +#define SOAP_XML_CANONICAL 0x00004000 /* EXC C14N canonical XML */ +#define SOAP_XML_TREE 0x00008000 /* emit XML tree (no id/ref) */ +#define SOAP_XML_GRAPH 0x00010000 +#define SOAP_XML_NIL 0x00020000 +#define SOAP_XML_DOM 0x00040000 +#define SOAP_XML_SEC 0x00080000 /* reserved for WS security */ + +#define SOAP_C_NOIOB 0x00100000 /* don't fault on array index out of bounds (just ignore) */ +#define SOAP_C_UTFSTRING 0x00200000 /* (de)serialize strings with UTF8 content */ +#define SOAP_C_MBSTRING 0x00400000 /* (de)serialize strings with multi-byte content */ +#define SOAP_C_NILSTRING 0x00800000 /* serialize empty strings as nil (omitted) */ + +#define SOAP_DOM_TREE 0x01000000 +#define SOAP_DOM_NODE 0x02000000 +#define SOAP_DOM_ASIS 0x04000000 + +#define SOAP_MIME_POSTCHECK 0x10000000 /* MIME flag (internal) */ + +#define SOAP_IO_DEFAULT SOAP_IO_FLUSH + +/* SSL client/server authentication settings */ + +#define SOAP_SSL_NO_AUTHENTICATION 0x00 /* for testing purposes */ +#define SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION 0x01 /* client requires server to authenticate */ +#define SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION 0x02 /* server requires client to authenticate */ +#define SOAP_SSL_SKIP_HOST_CHECK 0x04 /* client does not check the common name of the host in certificate */ +#define SOAP_SSL_RSA 0x06 /* use RSA */ +#define SOAP_SSLv3_TLSv1 0x00 /* SSL v3 and TLS v1 support by default */ +#define SOAP_SSLv3 0x10 /* SSL v3 only */ +#define SOAP_TLSv1 0x20 /* TLS v1 only */ + +#define SOAP_SSL_DEFAULT (SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION | SOAP_SSLv3_TLSv1) + +/* state */ + +#define SOAP_INIT 1 +#define SOAP_COPY 2 + +#define soap_check_state(soap) (!(soap) || ((soap)->state != SOAP_INIT && (soap)->state != SOAP_COPY)) + +/* part */ + +#define SOAP_BEGIN 0 +#define SOAP_IN_ENVELOPE 2 +#define SOAP_IN_HEADER 3 +#define SOAP_END_HEADER 4 +#define SOAP_NO_BODY 5 +#define SOAP_IN_BODY 6 +#define SOAP_END_BODY 7 +#define SOAP_END_ENVELOPE 8 +#define SOAP_END 9 +#define SOAP_BEGIN_SECURITY 10 +#define SOAP_IN_SECURITY 11 +#define SOAP_END_SECURITY 12 + +/* DEBUG macros */ + +#ifndef WITH_LEAN +# ifdef DEBUG +# ifndef SOAP_DEBUG +# define SOAP_DEBUG +# endif +# ifndef SOAP_MEM_DEBUG +# define SOAP_MEM_DEBUG +# endif +# endif +#endif + +#ifdef SOAP_MEM_DEBUG +# ifndef SOAP_MALLOC +# define SOAP_MALLOC(soap, size) soap_track_malloc(soap, __FILE__, __LINE__, size) +# endif +# ifndef SOAP_FREE +# define SOAP_FREE(soap, ptr) soap_track_free(soap, __FILE__, __LINE__, ptr) +# endif +#endif + +#ifndef SOAP_MALLOC /* use libc malloc */ +# define SOAP_MALLOC(soap, size) malloc(size) +#endif + +#ifndef SOAP_FREE /* use libc free */ +# define SOAP_FREE(soap, ptr) free(ptr) +#endif + +#ifdef SOAP_DEBUG +# ifndef SOAP_MESSAGE +# define SOAP_MESSAGE fprintf +# endif +# ifndef DBGLOG +# define DBGLOG(DBGFILE, CMD) \ +{ if (soap)\ + { if (!soap->fdebug[SOAP_INDEX_##DBGFILE])\ + soap_open_logfile((struct soap*)soap, SOAP_INDEX_##DBGFILE);\ + if (soap->fdebug[SOAP_INDEX_##DBGFILE])\ + { FILE *fdebug = soap->fdebug[SOAP_INDEX_##DBGFILE];\ + CMD;\ + fflush(fdebug);\ + }\ + }\ +} +# endif +# ifndef DBGMSG +# define DBGMSG(DBGFILE, MSG, LEN) \ +{ if (soap)\ + { if (!soap->fdebug[SOAP_INDEX_##DBGFILE])\ + soap_open_logfile((struct soap*)soap, SOAP_INDEX_##DBGFILE);\ + if (soap->fdebug[SOAP_INDEX_##DBGFILE])\ + { fwrite((MSG), 1, (LEN), soap->fdebug[SOAP_INDEX_##DBGFILE]);\ + fflush(soap->fdebug[SOAP_INDEX_##DBGFILE]);\ + }\ + }\ +} +# endif +# ifndef DGBFUN +# define DBGFUN(FNAME) DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): %s()\n", __FILE__, __LINE__, FNAME)) +# define DBGFUN1(FNAME, FMT, ARG) DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): %s("FMT")\n", __FILE__, __LINE__, FNAME, (ARG))) +# define DBGFUN2(FNAME, FMT1, ARG1, FMT2, ARG2) DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): %s("FMT1", "FMT2")\n", __FILE__, __LINE__, FNAME, (ARG1), (ARG2))) +# define DBGFUN3(FNAME, FMT1, ARG1, FMT2, ARG2, FMT3, ARG3) DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): %s("FMT1", "FMT2", "FMT3")\n", __FILE__, __LINE__, FNAME, (ARG1), (ARG2), (ARG3))) +# endif +# ifndef DBGHEX +# define DBGHEX(DBGFILE, MSG, LEN) \ +{ if (soap)\ + { if (!soap->fdebug[SOAP_INDEX_##DBGFILE])\ + soap_open_logfile(soap, SOAP_INDEX_##DBGFILE);\ + if (soap->fdebug[SOAP_INDEX_##DBGFILE])\ + { int i; char *s;\ + for (s = (char*)(MSG), i = (LEN); i; i--)\ + fprintf(soap->fdebug[SOAP_INDEX_##DBGFILE], "%2.2X ", (int)*s++&0xFF);\ + fflush(soap->fdebug[SOAP_INDEX_##DBGFILE]);\ + }\ + }\ +} +# endif +#else +# define DBGLOG(DBGFILE, CMD) +# define DBGMSG(DBGFILE, MSG, LEN) +# define DBGFUN(FNAME) +# define DBGFUN1(FNAME, FMT, ARG) +# define DBGFUN2(FNAME, FMT1, ARG1, FMT2, ARG2) +# define DBGFUN3(FNAME, FMT1, ARG1, FMT2, ARG2, FMT3, ARG3) +# define DBGHEX(DBGFILE, MSG, LEN) +#endif + +/* UCS-4 requires 32 bits (0-7FFFFFFF, the sign bit is used by gSOAP to distinguish XML entities) */ +typedef soap_int32 soap_wchar; + +/* namespace table row */ +struct Namespace +{ const char *id; + const char *ns; + const char *in; + char *out; +}; + +/* namespace stack */ +struct soap_nlist +{ struct soap_nlist *next; + unsigned int level; /* nesting depth level */ + short index; /* corresponding entry in ns mapping table */ + char *ns; /* only set when parsed ns URI is not in the ns mapping table */ + char id[1]; /* the actual string value flows into the allocated region below this struct */ +}; + +/* block stack for nested block allocations */ +struct soap_blist +{ struct soap_blist *next; + char *ptr; + size_t size; +}; + +/* array layout */ +struct soap_array +{ void *__ptr; + int __size; +}; + +/* pointer serialization management */ +struct soap_plist +{ struct soap_plist *next; + const void *ptr; + const struct soap_array *array; + int type; + int id; + char mark1; + char mark2; +}; + +/* block allocation for pointer serialization management */ +struct soap_pblk +{ struct soap_pblk *next; + struct soap_plist plist[SOAP_PTRBLK]; +}; + +#ifdef SOAP_MEM_DEBUG +/* malloc/free tracking for debugging */ +struct soap_mlist +{ struct soap_mlist *next; + const void *ptr; + const char *file; + int line; + short live; +}; +#endif + +/* class allocation list */ +struct soap_clist +{ struct soap_clist *next; + void *ptr; + int type; + int size; + void (*fdelete)(struct soap_clist*); +}; + +/* attributes */ +struct soap_attribute +{ struct soap_attribute *next; + char *value; + size_t size; + char *ns; + short visible; + char name[1]; /* the actual name string flows into the allocated region below this struct */ +}; + +#ifndef WITH_LEAN +struct soap_cookie +{ struct soap_cookie *next; + char *name; + char *value; + char *domain; + char *path; + time_t expire; /* client-side: local time to expire */ + long maxage; /* server-side: seconds to expire */ + unsigned int version; + short secure; + short session; /* server-side */ + short env; /* server-side: got cookie from client and should not be (re)send */ + short modified; /* server-side: client cookie was modified and should be send */ +}; +#endif + +#ifdef __cplusplus +SOAP_FMAC1 struct soap_multipart* SOAP_FMAC2 soap_next_multipart(struct soap_multipart*); + +class soap_multipart_iterator +{ public: + struct soap_multipart *content; + bool operator==(const soap_multipart_iterator& iter) const + { return content == iter.content; } + bool operator!=(const soap_multipart_iterator& iter) const + { return content != iter.content; } + struct soap_multipart &operator*() const + { return *content; } + soap_multipart_iterator &operator++() + { content = soap_next_multipart(content); return *this; } + soap_multipart_iterator() : content(NULL) + { } + soap_multipart_iterator(struct soap_multipart *p) : content(p) + { } +}; +#endif + +#ifndef WITH_LEANER +struct soap_dime +{ size_t count; + size_t size; + size_t chunksize; + size_t buflen; + char flags; + char *ptr; + const char *id; + const char *type; + const char *options; + struct soap_multipart *list; /* list of DIME attachments received */ + struct soap_multipart *first, *last; /* temporary in/out queue */ +#ifdef __cplusplus + soap_multipart_iterator begin() + { soap_multipart_iterator iter(list); return iter; }; + soap_multipart_iterator end() + { soap_multipart_iterator iter(NULL); return iter; }; +#endif +}; +#endif + +#ifndef WITH_LEANER +struct soap_mime +{ char *boundary; /* MIME boundary */ + const char *start; /* MIME start ID */ + struct soap_multipart *list; /* list of MIME attachments received */ + struct soap_multipart *first, *last; /* temporary in/out queue */ +#ifdef __cplusplus + soap_multipart_iterator begin() + { soap_multipart_iterator iter(list); return iter; }; + soap_multipart_iterator end() + { soap_multipart_iterator iter(NULL); return iter; }; +#endif +}; +#endif + +#ifndef WITH_LEANER +/* RFC2045 MIME content transfer encodings */ +enum soap_mime_encoding +{ SOAP_MIME_NONE, + SOAP_MIME_7BIT, + SOAP_MIME_8BIT, + SOAP_MIME_BINARY, + SOAP_MIME_QUOTED_PRINTABLE, + SOAP_MIME_BASE64, + SOAP_MIME_IETF_TOKEN, + SOAP_MIME_X_TOKEN +}; +#endif + +#ifndef WITH_LEANER +/* DIME/MIME multipart list */ +struct soap_multipart +{ struct soap_multipart *next; + char *ptr; /* points to raw data content */ + size_t size; /* size of data content */ + const char *id; /* DIME/MIME content ID or form data name */ + const char *type; /* DIME/MIME type (MIME type format) */ + const char *options; /* DIME options */ + enum soap_mime_encoding encoding; /* MIME Content-Transfer-Encoding */ + const char *location; /* MIME Content-Location (optional) */ + const char *description; /* MIME Content-Description (optional) */ +#ifdef __cplusplus + typedef soap_multipart_iterator iterator; +#endif +}; +#endif + +#ifndef WITH_LEANER +/* attachment DIME and MTOM XOP forwarding */ +struct soap_xlist +{ struct soap_xlist *next; + unsigned char **ptr; + int *size; + char *id; + char **type; + char **options; +}; +#endif + +/******************************************************************************/ + +#ifndef WITH_LEANER +#ifdef __cplusplus +class soap_dom_attribute_iterator +{ public: + struct soap_dom_attribute *att; + const char *nstr; + const char *name; + bool operator==(const soap_dom_attribute_iterator&) const; + bool operator!=(const soap_dom_attribute_iterator&) const; + struct soap_dom_attribute &operator*() const; + soap_dom_attribute_iterator &operator++(); + soap_dom_attribute_iterator(); + soap_dom_attribute_iterator(struct soap_dom_attribute*); + ~soap_dom_attribute_iterator(); +}; +#endif +#endif + +#ifndef WITH_LEANER +struct soap_dom_attribute +{ struct soap_dom_attribute *next; + const char *nstr; + char *name; + char *data; + wchar_t *wide; + struct soap *soap; +#ifdef __cplusplus + typedef soap_dom_attribute_iterator iterator; + struct soap_dom_attribute &set(const char *nstr, const char *name); /* set namespace and name */ + struct soap_dom_attribute &set(const char *data); /* set data */ + soap_dom_attribute_iterator begin(); + soap_dom_attribute_iterator end(); + soap_dom_attribute_iterator find(const char *nstr, const char *name); + void unlink(); + soap_dom_attribute(); + soap_dom_attribute(struct soap *soap); + soap_dom_attribute(struct soap *soap, const char *nstr, const char *name, const char *data); + ~soap_dom_attribute(); +#endif +}; +#endif + +#ifndef WITH_LEANER +#ifdef __cplusplus +class soap_dom_element_iterator +{ public: + struct soap_dom_element *elt; + const char *nstr; + const char *name; + int type; + bool operator==(const soap_dom_element_iterator&) const; + bool operator!=(const soap_dom_element_iterator&) const; + struct soap_dom_element &operator*() const; + soap_dom_element_iterator &operator++(); + soap_dom_element_iterator(); + soap_dom_element_iterator(struct soap_dom_element*); + ~soap_dom_element_iterator(); +}; +#endif +#endif + +#ifndef WITH_LEANER +struct soap_dom_element +{ struct soap_dom_element *next; /* next sibling */ + struct soap_dom_element *prnt; /* parent */ + struct soap_dom_element *elts; /* list of child elements */ + struct soap_dom_attribute *atts; /* list of attributes */ + const char *nstr; /* namespace string */ + char *name; /* element tag name */ + char *data; /* element content data (with SOAP_C_UTFSTRING flag set) */ + wchar_t *wide; /* element content data */ + int type; /* optional: serialized C/C++ data type */ + void *node; /* optional: pointer to serialized C/C++ data */ + char *head; /* leading whitespace to start tag */ + char *tail; /* leading whitespace to end tag */ + struct soap *soap; /* soap context that manages this node */ +#ifdef __cplusplus + typedef soap_dom_element_iterator iterator; + struct soap_dom_element &set(const char *nstr, const char *name); + struct soap_dom_element &set(const char *data); + struct soap_dom_element &set(void *node, int type); + struct soap_dom_element &add(struct soap_dom_element*); + struct soap_dom_element &add(struct soap_dom_element&); + struct soap_dom_element &add(struct soap_dom_attribute*); + struct soap_dom_element &add(struct soap_dom_attribute&); + soap_dom_element_iterator begin(); + soap_dom_element_iterator end(); + soap_dom_element_iterator find(const char *nstr, const char *name); + soap_dom_element_iterator find(int type); + void unlink(); + soap_dom_element(); + soap_dom_element(struct soap *soap); + soap_dom_element(struct soap *soap, const char *nstr, const char *name); + soap_dom_element(struct soap *soap, const char *nstr, const char *name, const char *data); + soap_dom_element(struct soap *soap, const char *nstr, const char *name, void *node, int type); + ~soap_dom_element(); +#endif +}; +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_dom_next_element(struct soap_dom_element *elt); +SOAP_FMAC1 struct soap_dom_attribute * SOAP_FMAC2 soap_dom_next_attribute(struct soap_dom_attribute *att); +#endif + +#if defined(__cplusplus) && !defined(WITH_LEAN) +} +extern std::ostream &operator<<(std::ostream&, const struct soap_dom_element&); +extern std::istream &operator>>(std::istream&, struct soap_dom_element&); +extern "C" { +#endif + +/******************************************************************************/ + +#ifdef WIN32 +# ifdef SOAP_STD_EXPORTS +# define SOAP_STD_API __declspec(dllexport) +# else +# define SOAP_STD_API +# endif +#else +# define SOAP_STD_API +#endif + +struct SOAP_STD_API soap +{ short state; /* 0 = uninitialized, 1 = initialized, 2 = copy of another soap struct */ + short version; /* 1 = SOAP1.1 and 2 = SOAP1.2 (set automatically from namespace URI in nsmap table) */ + soap_mode mode; + soap_mode imode; + soap_mode omode; + const char *float_format; /* user-definable format string for floats (<1024 chars) */ + const char *double_format; /* user-definable format string for doubles (<1024 chars) */ + const char *dime_id_format; /* user-definable format string for integer DIME id ( 0, gives socket recv timeout in seconds, < 0 in usec */ + int send_timeout; /* when > 0, gives socket send timeout in seconds, < 0 in usec */ + int connect_timeout; /* when > 0, gives socket connect() timeout in seconds, < 0 in usec */ + int accept_timeout; /* when > 0, gives socket accept() timeout in seconds, < 0 in usec */ + int socket_flags; /* socket recv() and send() flags, e.g. set to MSG_NOSIGNAL to disable sigpipe */ + int connect_flags; /* connect() SOL_SOCKET sockopt flags, e.g. set to SO_DEBUG to debug socket */ + int bind_flags; /* bind() SOL_SOCKET sockopt flags, e.g. set to SO_REUSEADDR to enable reuse */ + int accept_flags; /* accept() SOL_SOCKET sockopt flags */ + const struct Namespace *namespaces; /* Pointer to global namespace mapping table */ + struct Namespace *local_namespaces; /* Local namespace mapping table */ + struct soap_nlist *nlist; /* namespace stack */ + struct soap_blist *blist; /* block allocation stack */ + struct soap_clist *clist; /* class instance allocation list */ + void *alist; /* memory allocation (malloc) list */ + struct soap_ilist *iht[SOAP_IDHASH]; + struct soap_plist *pht[SOAP_PTRHASH]; + struct soap_pblk *pblk; /* plist block allocation */ + short pidx; /* plist block allocation */ + struct SOAP_ENV__Header *header; + struct SOAP_ENV__Fault *fault; + int idnum; + void *user; /* to pass user-defined data */ + struct soap_plugin *plugins; /* linked list of plug-in data */ + char *userid; /* HTTP Basic authorization userid */ + char *passwd; /* HTTP Basic authorization passwd */ + int (*fpost)(struct soap*, const char*, const char*, int, const char*, const char*, size_t); + int (*fget)(struct soap*); + int (*fform)(struct soap*); + int (*fposthdr)(struct soap*, const char*, const char*); + int (*fresponse)(struct soap*, int, size_t); + int (*fparse)(struct soap*); + int (*fparsehdr)(struct soap*, const char*, const char*); + int (*fheader)(struct soap*); + int (*fresolve)(struct soap*, const char*, struct in_addr* inaddr); + int (*fconnect)(struct soap*, const char*, const char*, int); + int (*fdisconnect)(struct soap*); + int (*fclosesocket)(struct soap*, SOAP_SOCKET); + int (*fshutdownsocket)(struct soap*, SOAP_SOCKET, int); + int (*fopen)(struct soap*, const char*, const char*, int); + int (*faccept)(struct soap*, int, struct sockaddr*, int *n); + int (*fclose)(struct soap*); + int (*fsend)(struct soap*, const char*, size_t); + size_t (*frecv)(struct soap*, char*, size_t); + int (*fpoll)(struct soap*); + void (*fseterror)(struct soap*, const char **c, const char **s); + int (*fignore)(struct soap*, const char*); + int (*fserveloop)(struct soap*); + void *(*fplugin)(struct soap*, const char*); + void *(*fmalloc)(struct soap*, size_t); +#ifndef WITH_LEANER + int (*fprepareinit)(struct soap*); + int (*fpreparesend)(struct soap*, const char*, size_t); + int (*fpreparerecv)(struct soap*, const char*, size_t); + int (*fpreparefinal)(struct soap*); + void *(*fdimereadopen)(struct soap*, void*, const char*, const char*, const char*); + void *(*fdimewriteopen)(struct soap*, const char*, const char*, const char*); + void (*fdimereadclose)(struct soap*, void*); + void (*fdimewriteclose)(struct soap*, void*); + size_t (*fdimeread)(struct soap*, void*, char*, size_t); + int (*fdimewrite)(struct soap*, void*, const char*, size_t); + void *(*fmimereadopen)(struct soap*, void*, const char*, const char*, const char*); + void *(*fmimewriteopen)(struct soap*, void*, const char*, const char*, const char*, enum soap_mime_encoding); + void (*fmimereadclose)(struct soap*, void*); + void (*fmimewriteclose)(struct soap*, void*); + size_t (*fmimeread)(struct soap*, void*, char*, size_t); + int (*fmimewrite)(struct soap*, void*, const char*, size_t); +#endif + int master; + int socket; +#if defined(__cplusplus) && !defined(WITH_LEAN) + std::ostream *os; + std::istream *is; +#else + void *os; /* preserve alignment */ + void *is; /* preserve alignment */ +#endif +#ifndef UNDER_CE + int sendfd; + int recvfd; +#else + FILE *sendfd; + FILE *recvfd; +#endif + size_t bufidx; /* index in soap.buf[] */ + size_t buflen; /* length of soap.buf[] content */ + soap_wchar ahead; /* parser lookahead */ + short cdata; /* CDATA parser state */ + short body; /* parsed XML element has a body or not */ + unsigned int level; /* XML nesting level */ + size_t count; /* message length counter */ + size_t length; /* message length as set by HTTP header */ + char *labbuf; /* look-aside buffer */ + size_t lablen; /* look-aside buffer allocated length */ + size_t labidx; /* look-aside buffer index to available part */ + char buf[SOAP_BUFLEN];/* send and receive buffer */ + char tmpbuf[1024]; /* in/output buffer for HTTP/MIME headers, simpleType values, attribute names, and DIME must be >=1024 bytes */ + char msgbuf[1024]; /* in/output buffer for messages >=1024 bytes */ + char tag[SOAP_TAGLEN]; + char id[SOAP_TAGLEN]; + char href[SOAP_TAGLEN]; + char type[SOAP_TAGLEN]; + char arrayType[SOAP_TAGLEN]; + char arraySize[SOAP_TAGLEN]; + char arrayOffset[SOAP_TAGLEN]; + short other; + short position; + int positions[SOAP_MAXDIMS]; + short root; + struct soap_attribute *attributes; /* attribute list */ + short encoding; /* when set, output encodingStyle */ + short mustUnderstand; /* a mustUnderstand element was parsed or is output */ + short keep_alive; /* connection should be kept open */ + short null; /* parsed XML is xsi:nil */ + short ns; /* when not set, output full xmlns bindings */ + short part; /* parsing state */ + short alloced; + short peeked; + size_t chunksize; + size_t chunkbuflen; + char endpoint[SOAP_TAGLEN]; + char path[SOAP_TAGLEN]; + char host[SOAP_TAGLEN]; + char *action; + char *authrealm; /* HTTP authentication realm */ + char *prolog; /* XML declaration prolog */ + unsigned long ip; /* IP number */ + int port; /* port number */ + unsigned int max_keep_alive; + const char *proxy_http_version;/* HTTP version of proxy "1.0" or "1.1" */ + const char *proxy_host; /* Proxy Server host name */ + int proxy_port; /* Proxy Server port (default = 8080) */ + const char *proxy_userid; /* Proxy Authorization user name */ + const char *proxy_passwd; /* Proxy Authorization password */ + int status; /* -1 when request, else error code to be returned by server */ + int error; + int errmode; + int errnum; +#ifndef WITH_LEANER + struct soap_dom_element *dom; + struct soap_dime dime; + struct soap_mime mime; + struct soap_xlist *xlist; +#endif +#if !defined(WITH_LEAN) || defined(SOAP_DEBUG) + const char *logfile[SOAP_MAXLOGS]; + FILE *fdebug[SOAP_MAXLOGS]; + struct soap_mlist *mht[SOAP_PTRHASH]; +#endif +#ifndef WITH_LEAN + const char *c14ninclude; + const char *c14nexclude; + struct soap_cookie *cookies; + const char *cookie_domain; + const char *cookie_path; + int cookie_max; +#endif +#ifndef WITH_NOIO +#ifdef WITH_IPV6 + struct sockaddr_storage peer; /* IPv6: set by soap_accept and by UDP recv */ +#else + struct sockaddr_in peer; /* IPv4: set by soap_connect/soap_accept and by UDP recv */ +#endif +#endif + size_t peerlen; +#ifdef WITH_OPENSSL + int (*fsslauth)(struct soap*); + int (*fsslverify)(int, X509_STORE_CTX*); + BIO *bio; + SSL *ssl; + SSL_CTX *ctx; + unsigned short ssl_flags; + const char *keyfile; + const char *password; + const char *dhfile; + const char *cafile; + const char *capath; + const char *crlfile; + const char *randfile; + SSL_SESSION *session; + char session_host[SOAP_TAGLEN]; + int session_port; +#endif +#ifdef WITH_ZLIB + short zlib_state; /* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_INFLATE */ + short zlib_in; /* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_GZIP */ + short zlib_out; /* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_GZIP */ + z_stream d_stream; /* decompression stream */ + char z_buf[SOAP_BUFLEN]; /* buffer */ + size_t z_buflen; + unsigned short z_level; /* compression level to be used (0=none, 1=fast to 9=best) */ + uLong z_crc; /* internal gzip crc */ + float z_ratio_in; /* detected compression ratio compressed_length/length of inbound message */ + float z_ratio_out; /* detected compression ratio compressed_length/length of outbound message */ +#endif +#ifdef WMW_RPM_IO + void *rpmreqid; +#endif +#ifndef WITH_LEAN +#ifdef __cplusplus + soap(); + soap(soap_mode); + soap(soap_mode, soap_mode); + soap(struct soap&); + ~soap(); +#endif +#endif +}; + +struct soap_code_map +{ long code; + const char *string; +}; + +/* forwarding list */ +struct soap_flist +{ struct soap_flist *next; + int type; + void *ptr; + unsigned int level; + size_t len; + void (*fcopy)(struct soap*, int, int, void*, size_t, const void*, size_t); +}; + +/* id-ref forwarding list */ +struct soap_ilist +{ struct soap_ilist *next; + int type; + size_t size; + void *link; + void *copy; + struct soap_flist *flist; + void *ptr; + unsigned int level; + char id[1]; /* the actual id string value flows into the allocated region below this struct */ +}; + +struct soap_plugin +{ struct soap_plugin *next; + const char *id; + void *data; + int (*fcopy)(struct soap *soap, struct soap_plugin *dst, struct soap_plugin *src); + void (*fdelete)(struct soap *soap, struct soap_plugin *p); /* should delete fields of plugin only and not free(p) */ +}; + +#ifndef WITH_NONAMESPACES +extern SOAP_NMAC struct Namespace namespaces[]; +#endif + +#ifndef WITH_LEAN +# define soap_get0(soap) (((soap)->bufidx>=(soap)->buflen && soap_recv(soap)) ? EOF : (unsigned char)(soap)->buf[(soap)->bufidx]) +# define soap_get1(soap) (((soap)->bufidx>=(soap)->buflen && soap_recv(soap)) ? EOF : (unsigned char)(soap)->buf[(soap)->bufidx++]) +#else +soap_wchar soap_get0(struct soap*); +soap_wchar soap_get1(struct soap*); +#endif + +#define soap_revget1(soap) ((soap)->bufidx--) +#define soap_unget(soap, c) ((soap)->ahead = c) +#define soap_register_plugin(soap, plugin) soap_register_plugin_arg(soap, plugin, NULL) +#define soap_imode(soap, n) ((soap)->mode = (soap)->imode = (n)) +#define soap_set_imode(soap, n) ((soap)->imode |= (n)) +#define soap_clr_imode(soap, n) ((soap)->imode &= ~(n)) +#define soap_omode(soap, n) ((soap)->mode = (soap)->omode = (n)) +#define soap_set_omode(soap, n) ((soap)->omode |= (n)) +#define soap_clr_omode(soap, n) ((soap)->omode &= ~(n)) +#define soap_set_mode(soap, n) ((soap)->imode |= (n), (soap)->omode |= (n)) +#define soap_clr_mode(soap, n) ((soap)->imode &= ~(n), (soap)->omode &= ~(n)) +#define soap_destroy(soap) soap_delete((soap), NULL) + +#ifdef HAVE_STRRCHR +# define soap_strrchr(s, t) strrchr(s, t) +#else + SOAP_FMAC1 char* SOAP_FMAC2 soap_strrchr(const char *s, int t); +#endif + +#ifdef HAVE_STRTOL +# define soap_strtol(s, t, b) strtol(s, t, b) +#else + SOAP_FMAC1 long SOAP_FMAC2 soap_strtol(const char *s, char **t, int b); +#endif + +#ifdef HAVE_STRTOUL +# define soap_strtoul(s, t, b) strtoul(s, t, b) +#else + SOAP_FMAC1 unsigned long SOAP_FMAC2 soap_strtoul(const char *s, char **t, int b); +#endif + +#if defined(WITH_OPENSSL) +# define soap_random soap_rand() +SOAP_FMAC1 int SOAP_FMAC2 soap_rand(void); +#elif defined(HAVE_RANDOM) +# define soap_random (int)random() +#else +# define soap_random rand() +#endif + +#ifdef WITH_NOIDREF +# define soap_embedded(s, p, t) (0) +# define soap_id_lookup(s, i, p, t, n, k) (p) +# define soap_id_forward(s, h, p, len, st, tt, n, k, fc) (p) +# define soap_reference(s, a, t) (1) +# define soap_array_reference(s, p, a, n, t) (1) +# define soap_embed(s, p, a, n, t, pp) (0) +# define soap_embedded_id(s, i, p, t) (i) +# define soap_is_embedded(s, p) (0) +# define soap_is_single(s, p) (1) +# define soap_lookup_type(s, i) (0) +# define soap_getindependent(s) (0) +# define soap_putindependent(s) (0) +# define soap_getelement(s, n) (n) +# define soap_putelement(s, p, t, i, n) (0) +# define soap_markelement(s, p, n) (0) +#endif + +SOAP_FMAC1 void SOAP_FMAC2 soap_fault(struct soap*); +SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultcode(struct soap*); +SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultsubcode(struct soap*); +SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultstring(struct soap*); +SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultdetail(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_serializeheader(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putheader(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getheader(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_serializefault(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putfault(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getfault(struct soap*); + +SOAP_FMAC1 void SOAP_FMAC2 soap_ssl_init(void); +SOAP_FMAC1 int SOAP_FMAC2 soap_poll(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_connect_command(struct soap*, int, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_connect(struct soap*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_bind(struct soap*, const char*, int, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_accept(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_accept(struct soap*); +SOAP_FMAC1 const char * SOAP_FMAC2 soap_ssl_error(struct soap*, int); + +SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_server_context(struct soap*, unsigned short, const char*, const char*, const char*, const char*, const char*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_client_context(struct soap*, unsigned short, const char*, const char*, const char*, const char*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_puthttphdr(struct soap*, int status, size_t count); + +SOAP_FMAC1 const char* SOAP_FMAC2 soap_get_header_attribute(struct soap*, const char*, const char*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_decode_key(char*, size_t, const char*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_decode_val(char*, size_t, const char*); + +SOAP_FMAC1 size_t SOAP_FMAC2 soap_hash(const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_endpoint(struct soap*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_flush_raw(struct soap*, const char*, size_t); +SOAP_FMAC1 int SOAP_FMAC2 soap_flush(struct soap*); +SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_get(struct soap*); +SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_getchar(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_tag_cmp(const char*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_fault(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_sender_fault(struct soap*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_sender_fault_subcode(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_receiver_fault(struct soap*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_receiver_fault_subcode(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_sender_error(struct soap*, const char*, const char*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_receiver_error(struct soap*, const char*, const char*, int); + +SOAP_FMAC1 int SOAP_FMAC2 soap_send_raw(struct soap*, const char*, size_t); +SOAP_FMAC1 int SOAP_FMAC2 soap_recv_raw(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_recv(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_send(struct soap*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_send2(struct soap*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_send3(struct soap*, const char*, const char*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_pututf8(struct soap*, unsigned long); +SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_getutf8(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_putbase64(struct soap*, const unsigned char*, int); +SOAP_FMAC1 unsigned char* SOAP_FMAC2 soap_getbase64(struct soap*, int*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_puthex(struct soap*, const unsigned char*, int); +SOAP_FMAC1 unsigned char* SOAP_FMAC2 soap_gethex(struct soap*, int*); + +#ifndef WITH_LEANER +SOAP_FMAC1 int SOAP_FMAC2 soap_xop_forward(struct soap*, unsigned char**, int*, char**, char**, char**); +SOAP_FMAC1 int SOAP_FMAC2 soap_dime_forward(struct soap*, unsigned char**, int*, char**, char**, char**); +#endif + +#ifndef WITH_NOIDREF +SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_lookup_id(struct soap*, void *p, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_lookup(struct soap*, const void *p, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_enter(struct soap*, const void *p, const struct soap_array *a, int n, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_array_pointer_lookup(struct soap*, const void *p, const struct soap_array *a, int n, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_embed(struct soap *soap, const void *p, const struct soap_array *a, int n, const char *tag, int type); +SOAP_FMAC1 struct soap_ilist* SOAP_FMAC2 soap_lookup(struct soap*, const char*); +SOAP_FMAC1 struct soap_ilist* SOAP_FMAC2 soap_enter(struct soap*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_resolve(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_embedded(struct soap*, const void *p, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_reference(struct soap*, const void *p, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_array_reference(struct soap*, const void *p, const struct soap_array *a, int n, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_embedded_id(struct soap*, int id, const void *p, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_is_embedded(struct soap*, struct soap_plist*); +SOAP_FMAC1 int SOAP_FMAC2 soap_is_single(struct soap*, struct soap_plist*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_embedded(struct soap*, struct soap_plist*); +#endif + +SOAP_FMAC1 int SOAP_FMAC2 soap_begin_count(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_end_count(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_begin_send(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_end_send(struct soap*); + +SOAP_FMAC1 const struct soap_code_map* SOAP_FMAC2 soap_code(const struct soap_code_map*, const char*); +SOAP_FMAC1 long SOAP_FMAC2 soap_code_int(const struct soap_code_map*, const char*, long); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_code_str(const struct soap_code_map*, long); +SOAP_FMAC1 long SOAP_FMAC2 soap_code_bits(const struct soap_code_map*, const char*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_code_list(struct soap*, const struct soap_code_map*, long); + +SOAP_FMAC1 int SOAP_FMAC2 soap_getline(struct soap*, char*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_begin_recv(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_end_recv(struct soap*); + +SOAP_FMAC1 void* SOAP_FMAC2 soap_malloc(struct soap*, size_t); +SOAP_FMAC1 void SOAP_FMAC2 soap_dealloc(struct soap*, void*); +SOAP_FMAC1 struct soap_clist * SOAP_FMAC2 soap_link(struct soap*, void*, int, int, void (*fdelete)(struct soap_clist*)); +SOAP_FMAC1 void SOAP_FMAC2 soap_unlink(struct soap*, const void*); +SOAP_FMAC1 void SOAP_FMAC2 soap_free_temp(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_del(struct soap*); + +SOAP_FMAC1 void* SOAP_FMAC2 soap_track_malloc(struct soap*, const char*, int, size_t); +SOAP_FMAC1 void SOAP_FMAC2 soap_track_free(struct soap*, const char*, int, void*); + +#ifndef WITH_NOIDREF +SOAP_FMAC1 int SOAP_FMAC2 soap_lookup_type(struct soap*, const char *id); +SOAP_FMAC1 void* SOAP_FMAC2 soap_id_lookup(struct soap*, const char *id, void **p, int t, size_t n, unsigned int k); +SOAP_FMAC1 void* SOAP_FMAC2 soap_id_forward(struct soap*, const char *id, void *p, size_t len, int st, int tt, size_t n, unsigned int k, void(*fcopy)(struct soap*, int, int, void*, size_t, const void*, size_t)); +#endif +SOAP_FMAC1 void* SOAP_FMAC2 soap_id_enter(struct soap*, const char *id, void *p, int t, size_t n, unsigned int k, const char *type, const char *arrayType, void *(*finstantiate)(struct soap*, int, const char*, const char*, size_t*)); +SOAP_FMAC1 void SOAP_FMAC2 soap_fcopy(struct soap *soap, int st, int tt, void *p, size_t, const void *q, size_t n); + +SOAP_FMAC1 int SOAP_FMAC2 soap_size(const int *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_getoffsets(const char *, const int *, int *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_getsize(const char *, const char *, int *); +SOAP_FMAC1 int SOAP_FMAC2 soap_getsizes(const char *, int *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_getposition(const char *, int *); + +SOAP_FMAC1 char* SOAP_FMAC2 soap_putsize(struct soap*, const char *, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_putsizesoffsets(struct soap*, const char *, const int *, const int *, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_putsizes(struct soap*, const char *, const int *, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_putoffset(struct soap*, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_putoffsets(struct soap*, const int *, int); + +SOAP_FMAC1 int SOAP_FMAC2 soap_closesock(struct soap*); + +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_new(void); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_new1(soap_mode); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_new2(soap_mode, soap_mode); +SOAP_FMAC1 void SOAP_FMAC2 soap_free(struct soap*); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_copy(struct soap*); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_copy_context(struct soap*, struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_copy_stream(struct soap*, struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_init(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_init1(struct soap*, soap_mode); +SOAP_FMAC1 void SOAP_FMAC2 soap_init2(struct soap*, soap_mode, soap_mode); +SOAP_FMAC1 void SOAP_FMAC2 soap_done(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_cleanup(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_begin(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_end(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_delete(struct soap*, void*); + +#ifdef SOAP_DEBUG +SOAP_FMAC1 void SOAP_FMAC2 soap_set_recv_logfile(struct soap*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_sent_logfile(struct soap*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_test_logfile(struct soap*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_close_logfiles(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_open_logfile(struct soap*, int); +#endif + +SOAP_FMAC1 const char* SOAP_FMAC2 soap_value(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_match_tag(struct soap*, const char*, const char *); +SOAP_FMAC1 int SOAP_FMAC2 soap_match_array(struct soap*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_element(struct soap*, const char*, int, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_begin_out(struct soap*, const char *tag, int id, const char *type); +SOAP_FMAC1 int SOAP_FMAC2 soap_array_begin_out(struct soap*, const char *tag, int id, const char *type, const char *offset); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_ref(struct soap*, const char *tag, int id, int href); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_href(struct soap*, const char *tag, int id, const char *ref, const char *val); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_null(struct soap*, const char *tag, int id, const char *type); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_id(struct soap*, const char *tag, int id, const void *p, const struct soap_array *a, int d, const char *type, int n); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_result(struct soap*, const char *tag); +SOAP_FMAC1 void SOAP_FMAC2 soap_check_result(struct soap*, const char *tag); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_end_out(struct soap*, const char *tag); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_start_end_out(struct soap*, const char *tag); + +SOAP_FMAC1 int SOAP_FMAC2 soap_attribute(struct soap*, const char*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_element_begin_in(struct soap*, const char *tag, int nillable, const char *type); + +SOAP_FMAC1 int SOAP_FMAC2 soap_element_end_in(struct soap*, const char *tag); + +SOAP_FMAC1 int SOAP_FMAC2 soap_peek_element(struct soap*); + +SOAP_FMAC1 void SOAP_FMAC2 soap_retry(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_revert(struct soap*); + +SOAP_FMAC1 char* SOAP_FMAC2 soap_strdup(struct soap*, const char*); +SOAP_FMAC1 const char * SOAP_FMAC2 soap_strsearch(const char *big, const char *little); + +SOAP_FMAC1 int SOAP_FMAC2 soap_string_out(struct soap*, const char *s, int flag); +SOAP_FMAC1 char* SOAP_FMAC2 soap_string_in(struct soap*, int, long, long); + +#ifndef WITH_LEANER +SOAP_FMAC1 int SOAP_FMAC2 soap_wstring_out(struct soap*, const wchar_t *s, int flag); +SOAP_FMAC1 wchar_t* SOAP_FMAC2 soap_wstring_in(struct soap*, int, long, long); +#endif + +SOAP_FMAC1 int SOAP_FMAC2 soap_match_namespace(struct soap*, const char *, const char*, int n1, int n2); + +SOAP_FMAC1 int SOAP_FMAC2 soap_set_namespaces(struct soap*, const struct Namespace*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_local_namespaces(struct soap*); + +SOAP_FMAC1 void SOAP_FMAC2 soap_pop_namespace(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_push_namespace(struct soap*, const char *,const char *); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_current_namespace(struct soap *soap, const char *tag); + +SOAP_FMAC1 struct soap_nlist* SOAP_FMAC2 soap_lookup_ns(struct soap *soap, const char *tag, size_t n); + +SOAP_FMAC1 int SOAP_FMAC2 soap_store_lab(struct soap*, const char*, size_t); +SOAP_FMAC1 int SOAP_FMAC2 soap_append_lab(struct soap*, const char*, size_t); + +SOAP_FMAC1 int SOAP_FMAC2 soap_new_block(struct soap*); +SOAP_FMAC1 void* SOAP_FMAC2 soap_push_block(struct soap*, size_t); +SOAP_FMAC1 void SOAP_FMAC2 soap_pop_block(struct soap*); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_size_block(struct soap*, size_t); +SOAP_FMAC1 char* SOAP_FMAC2 soap_first_block(struct soap*); +SOAP_FMAC1 char* SOAP_FMAC2 soap_next_block(struct soap*); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_block_size(struct soap*); +SOAP_FMAC1 char* SOAP_FMAC2 soap_save_block(struct soap*, char*, int); +SOAP_FMAC1 void SOAP_FMAC2 soap_end_block(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_begin_out(struct soap*); +SOAP_FMAC1 int soap_envelope_end_out(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_begin_in(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_end_in(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_body_begin_out(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_body_end_out(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_body_begin_in(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_body_end_in(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_recv_header(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_response(struct soap*, int); + +SOAP_FMAC1 int SOAP_FMAC2 soap_send_empty_response(struct soap*, int status); +SOAP_FMAC1 int SOAP_FMAC2 soap_recv_empty_response(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_send_fault(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_recv_fault(struct soap*); + +#ifndef WITH_NOSTDLIB +SOAP_FMAC1 void SOAP_FMAC2 soap_print_fault(struct soap*, FILE*); +SOAP_FMAC1 void SOAP_FMAC2 soap_print_fault_location(struct soap*, FILE*); +#endif + +SOAP_FMAC1 int SOAP_FMAC2 soap_s2byte(struct soap*, const char*, char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2short(struct soap*, const char*, short*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2int(struct soap*, const char*, int*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2long(struct soap*, const char*, long*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2LONG64(struct soap*, const char*, LONG64*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2float(struct soap*, const char*, float*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2double(struct soap*, const char*, double*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedByte(struct soap*, const char*, unsigned char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedShort(struct soap*, const char*, unsigned short*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedInt(struct soap*, const char*, unsigned int*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedLong(struct soap*, const char*, unsigned long*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2ULONG64(struct soap*, const char*, ULONG64*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2string(struct soap*, const char*, char**); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2QName(struct soap*, const char*, char**); + +#ifndef WITH_LEAN +SOAP_FMAC1 int SOAP_FMAC2 soap_s2wchar(struct soap*, const char*, wchar_t**); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2dateTime(struct soap*, const char*, time_t*); +SOAP_FMAC1 char* SOAP_FMAC2 soap_s2base64(struct soap*, const unsigned char*, char*, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_s2hex(struct soap*, const unsigned char*, char*, int); +#endif + +SOAP_FMAC1 const char* SOAP_FMAC2 soap_byte2s(struct soap*, char); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_short2s(struct soap*, short); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_int2s(struct soap*, int); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_long2s(struct soap*, long); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_LONG642s(struct soap*, LONG64); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_float2s(struct soap*, float); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_double2s(struct soap*, double); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedByte2s(struct soap*, unsigned char); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedShort2s(struct soap*, unsigned short); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedInt2s(struct soap*, unsigned int); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedLong2s(struct soap*, unsigned long); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_ULONG642s(struct soap*, ULONG64); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_QName2s(struct soap*, const char*); + +#ifndef WITH_LEAN +SOAP_FMAC1 const char* SOAP_FMAC2 soap_wchar2s(struct soap*, const wchar_t*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_dateTime2s(struct soap*, time_t); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_base642s(struct soap*, const char*, char*, size_t, int*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_hex2s(struct soap*, const char*, char*, size_t, int*); +#endif + + +SOAP_FMAC1 int* SOAP_FMAC2 soap_inint(struct soap*, const char *tag, int *p, const char *, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_inbyte(struct soap*, const char *tag, char *p, const char *, int); +SOAP_FMAC1 long* SOAP_FMAC2 soap_inlong(struct soap*, const char *tag, long *p, const char *, int); +SOAP_FMAC1 LONG64* SOAP_FMAC2 soap_inLONG64(struct soap*, const char *tag, LONG64 *p, const char *, int); +SOAP_FMAC1 short* SOAP_FMAC2 soap_inshort(struct soap*, const char *tag, short *p, const char *, int); +SOAP_FMAC1 float* SOAP_FMAC2 soap_infloat(struct soap*, const char *tag, float *p, const char *, int); +SOAP_FMAC1 double* SOAP_FMAC2 soap_indouble(struct soap*, const char *tag, double *p, const char *, int); +SOAP_FMAC1 unsigned char* SOAP_FMAC2 soap_inunsignedByte(struct soap*, const char *tag, unsigned char *p, const char *, int); +SOAP_FMAC1 unsigned short* SOAP_FMAC2 soap_inunsignedShort(struct soap*, const char *tag, unsigned short *p, const char *, int); +SOAP_FMAC1 unsigned int* SOAP_FMAC2 soap_inunsignedInt(struct soap*, const char *tag, unsigned int *p, const char *, int); +SOAP_FMAC1 unsigned long* SOAP_FMAC2 soap_inunsignedLong(struct soap*, const char *tag, unsigned long *p, const char *, int); +SOAP_FMAC1 ULONG64* SOAP_FMAC2 soap_inULONG64(struct soap*, const char *tag, ULONG64 *p, const char *, int); +SOAP_FMAC1 char** SOAP_FMAC2 soap_instring(struct soap*, const char *tag, char **p, const char *, int, int, long, long); +SOAP_FMAC1 char** SOAP_FMAC2 soap_inliteral(struct soap*, const char *tag, char **p); + +#ifndef WITH_LEAN +SOAP_FMAC1 time_t* SOAP_FMAC2 soap_indateTime(struct soap*, const char *tag, time_t *p, const char *, int); +#endif + +#ifndef WITH_LEANER +SOAP_FMAC1 wchar_t** SOAP_FMAC2 soap_inwstring(struct soap*, const char *tag, wchar_t **p, const char *, int, long, long); +SOAP_FMAC1 wchar_t** SOAP_FMAC2 soap_inwliteral(struct soap*, const char *tag, wchar_t **p); +#endif + +SOAP_FMAC1 int SOAP_FMAC2 soap_outbyte(struct soap*, const char *tag, int id, const char *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outshort(struct soap*, const char *tag, int id, const short *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outint(struct soap*, const char *tag, int id, const int *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outlong(struct soap*, const char *tag, int id, const long *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outLONG64(struct soap*, const char *tag, int id, const LONG64 *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outfloat(struct soap*, const char *tag, int id, const float *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outdouble(struct soap*, const char *tag, int id, const double *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedByte(struct soap*, const char *tag, int id, const unsigned char *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedShort(struct soap*, const char *tag, int id, const unsigned short *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedInt(struct soap*, const char *tag, int id, const unsigned int *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedLong(struct soap*, const char *tag, int id, const unsigned long *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outULONG64(struct soap*, const char *tag, int id, const ULONG64 *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outstring(struct soap*, const char *tag, int id, char *const*p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outliteral(struct soap*, const char *tag, char *const*p, const char *type); + +#ifndef WITH_LEAN +SOAP_FMAC1 int SOAP_FMAC2 soap_outdateTime(struct soap*, const char *tag, int id, const time_t *p, const char *, int); +#endif + +#ifndef WITH_LEANER +SOAP_FMAC1 int SOAP_FMAC2 soap_outwstring(struct soap*, const char *tag, int id, wchar_t *const*p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outwliteral(struct soap*, const char *tag, wchar_t *const*p, const char *type); +#endif + +#ifndef WITH_LEANER +SOAP_FMAC1 int SOAP_FMAC2 soap_attachment(struct soap *, const char*, int, const void*, const struct soap_array*, const char*, const char*, const char*, int, const char*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_move(struct soap*, long); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_tell(struct soap*); +SOAP_FMAC1 char* SOAP_FMAC2 soap_dime_option(struct soap*, unsigned short, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getdimehdr(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getdime(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putdimehdr(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putdime(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getmimehdr(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getmime(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putmimehdr(struct soap*, struct soap_multipart*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putmime(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_dime(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_mime(struct soap*, const char *boundary, const char *start); +SOAP_FMAC1 void SOAP_FMAC2 soap_clr_dime(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_clr_mime(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_dime_attachment(struct soap*, char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_mime_attachment(struct soap*, char *ptr, size_t size, enum soap_mime_encoding encoding, const char *type, const char *id, const char *location, const char *description); +SOAP_FMAC1 void SOAP_FMAC2 soap_post_check_mime_attachments(struct soap *soap); +SOAP_FMAC1 int SOAP_FMAC2 soap_check_mime_attachments(struct soap *soap); +SOAP_FMAC1 struct soap_multipart* SOAP_FMAC2 soap_get_mime_attachment(struct soap *soap, void *handle); +SOAP_FMAC1 struct soap_multipart* SOAP_FMAC2 soap_next_multipart(struct soap_multipart*); +SOAP_FMAC1 int SOAP_FMAC2 soap_match_cid(struct soap*, const char*, const char*); +#endif + +SOAP_FMAC1 int SOAP_FMAC2 soap_register_plugin_arg(struct soap*, int (*fcreate)(struct soap*, struct soap_plugin*, void*), void*); +SOAP_FMAC1 void* SOAP_FMAC2 soap_lookup_plugin(struct soap*, const char*); + +SOAP_FMAC1 const char* SOAP_FMAC2 soap_attr_value(struct soap *soap, const char *name, int flag); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_attr(struct soap *soap, const char *name, const char *value); +SOAP_FMAC1 void SOAP_FMAC2 soap_clr_attr(struct soap *soap); + +#ifdef WITH_COOKIES +SOAP_FMAC1 void SOAP_FMAC2 soap_getcookies(struct soap *soap, const char *val); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_encode_cookie(const char*, char*, size_t); +SOAP_FMAC1 extern struct soap_cookie* SOAP_FMAC2 soap_set_cookie(struct soap*, const char*, const char*, const char*, const char*); +SOAP_FMAC1 extern struct soap_cookie* SOAP_FMAC2 soap_cookie(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern char* SOAP_FMAC2 soap_cookie_value(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern char* SOAP_FMAC2 soap_env_cookie_value(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern time_t SOAP_FMAC2 soap_cookie_expire(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern int SOAP_FMAC2 soap_set_cookie_expire(struct soap*, const char*, long, const char*, const char*); +SOAP_FMAC1 extern int SOAP_FMAC2 soap_set_cookie_session(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern int SOAP_FMAC2 soap_clr_cookie_session(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern void SOAP_FMAC2 soap_clr_cookie(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern int SOAP_FMAC2 soap_getenv_cookies(struct soap*); +SOAP_FMAC1 extern struct soap_cookie* SOAP_FMAC2 soap_copy_cookies(struct soap*, struct soap*); +SOAP_FMAC1 extern void SOAP_FMAC2 soap_free_cookies(struct soap*); +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif + diff --git a/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.9d.c b/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.9d.c new file mode 100644 index 0000000..efff89b --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.9d.c @@ -0,0 +1,14414 @@ +/* + +stdsoap2.c[pp] 2.7.9d + +gSOAP runtime + +gSOAP XML Web services tools +Copyright (C) 2000-2007, Robert van Engelen, Genivia Inc., All Rights Reserved. +This part of the software is released under one of the following licenses: +GPL, the gSOAP public license, or Genivia's license for commercial use. +-------------------------------------------------------------------------------- +Contributors: + +Wind River Systems Inc., for the following additions under gSOAP public license: + - vxWorks compatible (#define VXWORKS) +-------------------------------------------------------------------------------- +gSOAP public license. + +The contents of this file are subject to the gSOAP Public License Version 1.3 +(the "License"); you may not use this file except in compliance with the +License. You may obtain a copy of the License at +http://www.cs.fsu.edu/~engelen/soaplicense.html +Software distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +for the specific language governing rights and limitations under the License. + +The Initial Developer of the Original Code is Robert A. van Engelen. +Copyright (C) 2000-2007, Robert van Engelen, Genivia Inc., All Rights Reserved. +-------------------------------------------------------------------------------- +GPL license. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA + +Author contact information: +engelen@genivia.com / engelen@acm.org +-------------------------------------------------------------------------------- +A commercial use license is available from Genivia, Inc., contact@genivia.com +-------------------------------------------------------------------------------- + +Installation note: + +Win32 build needs winsock.dll (Visual C++ "wsock32.lib") +To do this in Visual C++ 6.0, go to "Project", "settings", select the "Link" +tab (the project file needs to be selected in the file view) and add +"wsock32.lib" to the "Object/library modules" entry + +On Mac OS X with gcc (GCC) 3.1 20020420 (prerelease) you MUST compile with +-fstack_check when using -O2 because gcc 3.1 has a bug that smashes the stack +when locally allocated data exceeds 64K. + +*/ + +#ifdef AS400 +# pragma convert(819) /* EBCDIC to ASCII */ +#endif + +#include "stdsoap2.h" + +#ifdef WIN32 +# pragma comment(lib, "wsock32.lib") +#endif + +#ifdef __cplusplus +SOAP_SOURCE_STAMP("@(#) stdsoap2.cpp ver 2.7.9d 2007-02-19 12:00:00 GMT") +extern "C" { +#else +SOAP_SOURCE_STAMP("@(#) stdsoap2.c ver 2.7.9d 2007-02-19 12:00:00 GMT") +#endif + +/* 8bit character representing unknown/nonrepresentable character data (e.g. not supported by current locale with multibyte support enabled) */ +#ifndef SOAP_UNKNOWN_CHAR +#define SOAP_UNKNOWN_CHAR (127) +#endif + +/* EOF=-1 */ +#define SOAP_LT (soap_wchar)(-2) /* XML character '<' */ +#define SOAP_TT (soap_wchar)(-3) /* XML character '' */ +#define SOAP_QT (soap_wchar)(-5) /* XML character '"' */ +#define SOAP_AP (soap_wchar)(-6) /* XML character ''' */ + +#define soap_blank(c) ((c) >= 0 && (c) <= 32) +#define soap_notblank(c) ((c) > 32) + +#ifdef WIN32 +#define soap_hash_ptr(p) ((PtrToUlong(p) >> 3) & (SOAP_PTRHASH - 1)) +#else +#define soap_hash_ptr(p) ((size_t)(((unsigned long)(p) >> 3) & (SOAP_PTRHASH-1))) +#endif + +#ifdef SOAP_DEBUG +static void soap_init_logs(struct soap*); +static void soap_close_logfile(struct soap*, int); +static void soap_set_logfile(struct soap*, int, const char*); +#endif + +#ifdef SOAP_MEM_DEBUG +static void soap_init_mht(struct soap*); +static void soap_free_mht(struct soap*); +static void soap_track_unlink(struct soap*, const void*); +#endif + +#ifndef PALM_2 +static int soap_set_error(struct soap*, const char*, const char*, const char*, const char*, int); +static int soap_copy_fault(struct soap*, const char*, const char*, const char*, const char*); +static int soap_getattrval(struct soap*, char*, size_t, soap_wchar); +#endif + +#ifndef PALM_1 +static soap_wchar soap_char(struct soap*); +static soap_wchar soap_get_pi(struct soap*); +static int soap_isxdigit(int); +static void *fplugin(struct soap*, const char*); +#ifndef WITH_NOIDREF +static void soap_update_ptrs(struct soap*, char*, char*, char*, char*); +static int soap_has_copies(struct soap*, const char*, const char*); +static void soap_init_iht(struct soap*); +static void soap_free_iht(struct soap*); +static void soap_init_pht(struct soap*); +static void soap_free_pht(struct soap*); +#endif +#endif + +#ifndef WITH_LEAN +static const char *soap_set_validation_fault(struct soap*, const char*, const char*); +static int soap_isnumeric(struct soap*, const char*); +static time_t soap_timegm(struct tm*); +static struct soap_nlist *soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized); +static void soap_pop_ns(struct soap *soap); +static void soap_utilize_ns(struct soap *soap, const char *tag, size_t n); +#endif + +#ifndef WITH_LEANER +#ifndef PALM_1 +static struct soap_multipart *soap_new_multipart(struct soap*, struct soap_multipart**, struct soap_multipart**, char*, size_t); +static int soap_putdimefield(struct soap*, const char*, size_t); +static char *soap_getdimefield(struct soap*, size_t); +static void soap_select_mime_boundary(struct soap*); +static int soap_valid_mime_boundary(struct soap*); +static void soap_resolve_attachment(struct soap*, struct soap_multipart*); +#endif +#endif + +#ifdef WITH_GZIP +static int soap_getgziphdr(struct soap*); +#endif + +#ifdef WITH_OPENSSL +static int ssl_init_done = 0; +static int ssl_auth_init(struct soap*); +static int ssl_verify_callback(int, X509_STORE_CTX*); +static int ssl_password(char*, int, int, void *); +/* This callback is included for future references. It should not be deleted +static DH *ssl_tmp_dh(SSL*, int, int); +*/ +#endif + +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +#ifndef PALM_1 +static const char *soap_decode(char*, size_t, const char*, const char*); +#endif +#endif + +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static soap_wchar soap_getchunkchar(struct soap*); +static const char *http_error(struct soap*, int); +static int http_post(struct soap*, const char*, const char*, int, const char*, const char*, size_t); +static int http_get(struct soap*); +static int http_send_header(struct soap*, const char*); +static int http_post_header(struct soap*, const char*, const char*); +static int http_response(struct soap*, int, size_t); +static int http_parse(struct soap*); +static int http_parse_header(struct soap*, const char*, const char*); +#endif +#endif + +#ifndef WITH_NOIO +#ifndef PALM_1 +static int fsend(struct soap*, const char*, size_t); +static size_t frecv(struct soap*, char*, size_t); +static int tcp_init(struct soap*); +static const char *tcp_error(struct soap*); +#ifndef WITH_LEAN +static size_t frecv_stop(struct soap*, char*, size_t); +#endif +#ifndef WITH_IPV6 +static int tcp_gethost(struct soap*, const char *addr, struct in_addr *inaddr); +#endif +static int tcp_connect(struct soap*, const char *endpoint, const char *host, int port); +static int tcp_accept(struct soap*, int, struct sockaddr*, int*); +static int tcp_disconnect(struct soap*); +static int tcp_closesocket(struct soap*, SOAP_SOCKET); +static int tcp_shutdownsocket(struct soap*, SOAP_SOCKET, int); +static const char *soap_strerror(struct soap*); +#endif +#endif + +#if defined(PALM) && !defined(PALM_2) +unsigned short errno; +#endif + +#ifndef PALM_1 +static const char soap_env1[42] = "http://schemas.xmlsoap.org/soap/envelope/"; +static const char soap_enc1[42] = "http://schemas.xmlsoap.org/soap/encoding/"; +static const char soap_env2[40] = "http://www.w3.org/2003/05/soap-envelope"; +static const char soap_enc2[40] = "http://www.w3.org/2003/05/soap-encoding"; +static const char soap_rpc[35] = "http://www.w3.org/2003/05/soap-rpc"; +#endif + +#ifndef PALM_1 +const struct soap_double_nan soap_double_nan = {0xFFFFFFFF, 0xFFFFFFFF}; +static const char soap_base64o[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char soap_base64i[81] = "\76XXX\77\64\65\66\67\70\71\72\73\74\75XXXXXXX\00\01\02\03\04\05\06\07\10\11\12\13\14\15\16\17\20\21\22\23\24\25\26\27\30\31XXXXXX\32\33\34\35\36\37\40\41\42\43\44\45\46\47\50\51\52\53\54\55\56\57\60\61\62\63"; +#endif + +#ifndef WITH_LEAN +static const char soap_indent[11] = "\n\t\t\t\t\t\t\t\t\t"; +/* Alternative indentation form for SOAP_XML_INDENT: +static const char soap_indent[21] = "\n "; +*/ +#endif + +#ifndef SOAP_CANARY +# define SOAP_CANARY (0xC0DE) +#endif + +static const char soap_padding[4] = "\0\0\0"; +#define SOAP_STR_PADDING (soap_padding) +#define SOAP_STR_EOS (soap_padding) +#define SOAP_NON_NULL (soap_padding) + +#ifndef WITH_LEAN +static const struct soap_code_map html_entity_codes[] = /* entities for XHTML parsing */ +{ { 160, "nbsp" }, + { 161, "iexcl" }, + { 162, "cent" }, + { 163, "pound" }, + { 164, "curren" }, + { 165, "yen" }, + { 166, "brvbar" }, + { 167, "sect" }, + { 168, "uml" }, + { 169, "copy" }, + { 170, "ordf" }, + { 171, "laquo" }, + { 172, "not" }, + { 173, "shy" }, + { 174, "reg" }, + { 175, "macr" }, + { 176, "deg" }, + { 177, "plusmn" }, + { 178, "sup2" }, + { 179, "sup3" }, + { 180, "acute" }, + { 181, "micro" }, + { 182, "para" }, + { 183, "middot" }, + { 184, "cedil" }, + { 185, "sup1" }, + { 186, "ordm" }, + { 187, "raquo" }, + { 188, "frac14" }, + { 189, "frac12" }, + { 190, "frac34" }, + { 191, "iquest" }, + { 192, "Agrave" }, + { 193, "Aacute" }, + { 194, "Acirc" }, + { 195, "Atilde" }, + { 196, "Auml" }, + { 197, "Aring" }, + { 198, "AElig" }, + { 199, "Ccedil" }, + { 200, "Egrave" }, + { 201, "Eacute" }, + { 202, "Ecirc" }, + { 203, "Euml" }, + { 204, "Igrave" }, + { 205, "Iacute" }, + { 206, "Icirc" }, + { 207, "Iuml" }, + { 208, "ETH" }, + { 209, "Ntilde" }, + { 210, "Ograve" }, + { 211, "Oacute" }, + { 212, "Ocirc" }, + { 213, "Otilde" }, + { 214, "Ouml" }, + { 215, "times" }, + { 216, "Oslash" }, + { 217, "Ugrave" }, + { 218, "Uacute" }, + { 219, "Ucirc" }, + { 220, "Uuml" }, + { 221, "Yacute" }, + { 222, "THORN" }, + { 223, "szlig" }, + { 224, "agrave" }, + { 225, "aacute" }, + { 226, "acirc" }, + { 227, "atilde" }, + { 228, "auml" }, + { 229, "aring" }, + { 230, "aelig" }, + { 231, "ccedil" }, + { 232, "egrave" }, + { 233, "eacute" }, + { 234, "ecirc" }, + { 235, "euml" }, + { 236, "igrave" }, + { 237, "iacute" }, + { 238, "icirc" }, + { 239, "iuml" }, + { 240, "eth" }, + { 241, "ntilde" }, + { 242, "ograve" }, + { 243, "oacute" }, + { 244, "ocirc" }, + { 245, "otilde" }, + { 246, "ouml" }, + { 247, "divide" }, + { 248, "oslash" }, + { 249, "ugrave" }, + { 250, "uacute" }, + { 251, "ucirc" }, + { 252, "uuml" }, + { 253, "yacute" }, + { 254, "thorn" }, + { 255, "yuml" }, + { 0, NULL } +}; +#endif + +#ifndef WITH_NOIO +#ifndef WITH_LEAN +static const struct soap_code_map h_error_codes[] = +{ +#ifdef HOST_NOT_FOUND + { HOST_NOT_FOUND, "Host not found" }, +#endif +#ifdef TRY_AGAIN + { TRY_AGAIN, "Try Again" }, +#endif +#ifdef NO_RECOVERY + { NO_RECOVERY, "No Recovery" }, +#endif +#ifdef NO_DATA + { NO_DATA, "No Data" }, +#endif +#ifdef NO_ADDRESS + { NO_ADDRESS, "No Address" }, +#endif + { 0, NULL } +}; +#endif +#endif + +#ifndef WITH_NOHTTP +#ifndef WITH_LEAN +static const struct soap_code_map h_http_error_codes[] = +{ { 200, "OK" }, + { 201, "Created" }, + { 202, "Accepted" }, + { 203, "Non-Authoritative Information" }, + { 204, "No Content" }, + { 205, "Reset Content" }, + { 206, "Partial Content" }, + { 300, "Multiple Choices" }, + { 301, "Moved Permanently" }, + { 302, "Found" }, + { 303, "See Other" }, + { 304, "Not Modified" }, + { 305, "Use Proxy" }, + { 307, "Temporary Redirect" }, + { 400, "Bad Request" }, + { 401, "Unauthorized" }, + { 402, "Payment Required" }, + { 403, "Forbidden" }, + { 404, "Not Found" }, + { 405, "Method Not Allowed" }, + { 406, "Not Acceptable" }, + { 407, "Proxy Authentication Required" }, + { 408, "Request Time-out" }, + { 409, "Conflict" }, + { 410, "Gone" }, + { 411, "Length Required" }, + { 412, "Precondition Failed" }, + { 413, "Request Entity Too Large" }, + { 414, "Request-URI Too Large" }, + { 415, "Unsupported Media Type" }, + { 416, "Requested range not satisfiable" }, + { 417, "Expectation Failed" }, + { 500, "Internal Server Error" }, + { 501, "Not Implemented" }, + { 502, "Bad Gateway" }, + { 503, "Service Unavailable" }, + { 504, "Gateway Time-out" }, + { 505, "HTTP Version not supported" }, + { 0, NULL } +}; +#endif +#endif + +#ifdef WITH_OPENSSL +static const struct soap_code_map h_ssl_error_codes[] = +{ +#define _SSL_ERROR(e) { e, #e } + _SSL_ERROR(SSL_ERROR_SSL), + _SSL_ERROR(SSL_ERROR_ZERO_RETURN), + _SSL_ERROR(SSL_ERROR_WANT_READ), + _SSL_ERROR(SSL_ERROR_WANT_WRITE), + _SSL_ERROR(SSL_ERROR_WANT_CONNECT), + _SSL_ERROR(SSL_ERROR_WANT_X509_LOOKUP), + _SSL_ERROR(SSL_ERROR_SYSCALL), + { 0, NULL } +}; +#endif + +#ifndef WITH_LEANER +static const struct soap_code_map mime_codes[] = +{ { SOAP_MIME_7BIT, "7bit" }, + { SOAP_MIME_8BIT, "8bit" }, + { SOAP_MIME_BINARY, "binary" }, + { SOAP_MIME_QUOTED_PRINTABLE, "quoted-printable" }, + { SOAP_MIME_BASE64, "base64" }, + { SOAP_MIME_IETF_TOKEN, "ietf-token" }, + { SOAP_MIME_X_TOKEN, "x-token" }, + { 0, NULL } +}; +#endif + +#ifdef WIN32 +static int tcp_done = 0; +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +fsend(struct soap *soap, const char *s, size_t n) +{ register int nwritten, err; +#if defined(__cplusplus) && !defined(WITH_LEAN) + if (soap->os) + { soap->os->write(s, n); + if (soap->os->good()) + return SOAP_OK; + return SOAP_EOF; + } +#endif + while (n) + { if (soap_valid_socket(soap->socket)) + { +#ifndef WITH_LEAN + if (soap->send_timeout) + { struct timeval timeout; + fd_set fd; + if (soap->send_timeout > 0) + { timeout.tv_sec = soap->send_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->send_timeout/1000000; + timeout.tv_usec = -soap->send_timeout%1000000; + } +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + return SOAP_FD_EXCEEDED; /* Hint: MUST increase FD_SETSIZE */ +#endif + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->socket, &fd); + for (;;) + { register int r; +#ifdef WITH_OPENSSL + if (soap->ssl) + r = select((SOAP_SOCKET)(soap->socket + 1), &fd, &fd, &fd, &timeout); + else +#endif + r = select((SOAP_SOCKET)(soap->socket + 1), NULL, &fd, &fd, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + return SOAP_EOF; + } + err = soap_socket_errno(soap->socket); + if (err != SOAP_EINTR && err != SOAP_EAGAIN) + { soap->errnum = err; + return SOAP_EOF; + } + } + } +#endif +#ifdef WITH_OPENSSL + if (soap->ssl) + nwritten = SSL_write(soap->ssl, s, n); + else if (soap->bio) + nwritten = BIO_write(soap->bio, s, n); + else +#endif +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + { if (soap->peerlen) + nwritten = sendto((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags, (struct sockaddr*)&soap->peer, soap->peerlen); + else + nwritten = send((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags); + /* retry and back-off algorithm */ + /* TODO: this is not very clear from specs so verify and limit conditions under which we should loop (e.g. ENOBUFS) */ + if (nwritten < 0) + { struct timeval timeout; + fd_set fd; + int udp_repeat; + int udp_delay; +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + return SOAP_FD_EXCEEDED; /* Hint: MUST increase FD_SETSIZE */ +#endif + if ((soap->connect_flags & SO_BROADCAST)) + udp_repeat = 3; /* SOAP-over-UDP MULTICAST_UDP_REPEAT - 1 */ + else + udp_repeat = 1; /* SOAP-over-UDP UNICAST_UDP_REPEAT - 1 */ + udp_delay = (soap_random % 201) + 50; /* UDP_MIN_DELAY .. UDP_MAX_DELAY */ + do + { timeout.tv_sec = 0; + timeout.tv_usec = 1000 * udp_delay; /* ms */ + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->socket, &fd); + select((SOAP_SOCKET)(soap->socket + 1), NULL, NULL, &fd, &timeout); + if (soap->peerlen) + nwritten = sendto((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags, (struct sockaddr*)&soap->peer, soap->peerlen); + else + nwritten = send((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags); + udp_delay <<= 1; + if (udp_delay > 500) /* UDP_UPPER_DELAY */ + udp_delay = 500; + } + while (nwritten < 0 && --udp_repeat > 0); + } + } + else +#endif +#if !defined(PALM) && !defined(AS400) + nwritten = send((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags); +#else + nwritten = send((SOAP_SOCKET)soap->socket, (void*)s, n, soap->socket_flags); +#endif + if (nwritten <= 0) + { register int r; +#ifdef WITH_OPENSSL + if (soap->ssl && (r = SSL_get_error(soap->ssl, nwritten)) != SSL_ERROR_NONE && r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE) + return SOAP_EOF; +#endif + err = soap_socket_errno(soap->socket); + if (err == SOAP_EWOULDBLOCK || err == SOAP_EAGAIN) + { +#ifndef WITH_LEAN + struct timeval timeout; + fd_set fd; + if (soap->send_timeout > 0) + { timeout.tv_sec = soap->send_timeout; + timeout.tv_usec = 0; + } + else if (soap->send_timeout < 0) + { timeout.tv_sec = -soap->send_timeout/1000000; + timeout.tv_usec = -soap->send_timeout%1000000; + } + else + { timeout.tv_sec = 0; + timeout.tv_usec = 10000; + } +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + return SOAP_FD_EXCEEDED; /* Hint: MUST increase FD_SETSIZE */ +#endif + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->socket, &fd); +#ifdef WITH_OPENSSL + if (soap->ssl && r == SSL_ERROR_WANT_READ) + r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout); + else + r = select((SOAP_SOCKET)(soap->socket + 1), NULL, &fd, &fd, &timeout); +#else + r = select((SOAP_SOCKET)(soap->socket + 1), NULL, &fd, &fd, &timeout); +#endif + if (r < 0 && (r = soap_socket_errno(soap->socket)) != SOAP_EINTR) + { soap->errnum = r; + return SOAP_EOF; + } +#endif + } + else if (err && err != SOAP_EINTR) + { soap->errnum = err; + return SOAP_EOF; + } + nwritten = 0; /* and call write() again */ + } + } + else + { +#ifdef WITH_FASTCGI + nwritten = fwrite((void*)s, 1, n, stdout); + fflush(stdout); +#else +#ifdef UNDER_CE + nwritten = fwrite(s, 1, n, soap->sendfd); +#else +#ifdef VXWORKS +#ifdef WMW_RPM_IO + if (soap->rpmreqid) + nwritten = (httpBlockPut(soap->rpmreqid, s, n) == 0) ? n : -1; + else +#endif + nwritten = fwrite(s, sizeof(char), n, fdopen(soap->sendfd, "w")); +#else + nwritten = write((SOAP_SOCKET)soap->sendfd, s, n); +#endif +#endif +#endif + if (nwritten <= 0) + { err = soap_errno; + if (err && err != SOAP_EINTR && err != SOAP_EWOULDBLOCK && err != SOAP_EAGAIN) + { soap->errnum = err; + return SOAP_EOF; + } + nwritten = 0; /* and call write() again */ + } + } + n -= nwritten; + s += nwritten; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send_raw(struct soap *soap, const char *s, size_t n) +{ if (!n) + return SOAP_OK; + if (soap->mode & SOAP_IO_LENGTH) + { soap->count += n; +#ifndef WITH_LEANER + if (soap->fpreparesend && (soap->mode & SOAP_IO) != SOAP_IO_STORE) + return soap->error = soap->fpreparesend(soap, s, n); +#endif + return SOAP_OK; + } + if (soap->mode & SOAP_IO) + { register size_t i = SOAP_BUFLEN - soap->bufidx; + while (n >= i) + { memcpy(soap->buf + soap->bufidx, s, i); + soap->bufidx = SOAP_BUFLEN; + if (soap_flush(soap)) + return soap->error; + s += i; + n -= i; + i = SOAP_BUFLEN; + } + memcpy(soap->buf + soap->bufidx, s, n); + soap->bufidx += n; + return SOAP_OK; + } + return soap_flush_raw(soap, s, n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_flush(struct soap *soap) +{ register int n = soap->bufidx; + if (n) + { soap->bufidx = 0; +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { soap->d_stream.next_in = (Byte*)soap->buf; + soap->d_stream.avail_in = (unsigned int)n; +#ifdef WITH_GZIP + soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)n); +#endif + do + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating %u bytes\n", soap->d_stream.avail_in)); + if (deflate(&soap->d_stream, Z_NO_FLUSH) != Z_OK) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to deflate: %s\n", soap->d_stream.msg?soap->d_stream.msg:"")); + return soap->error = SOAP_ZLIB_ERROR; + } + if (!soap->d_stream.avail_out) + { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN)) + return soap->error; + soap->d_stream.next_out = (Byte*)soap->z_buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + } + } while (soap->d_stream.avail_in); + } + else +#endif + return soap_flush_raw(soap, soap->buf, n); + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_flush_raw(struct soap *soap, const char *s, size_t n) +{ if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) + { register char *t; + if (!(t = (char*)soap_push_block(soap, n))) + return soap->error = SOAP_EOM; + memcpy(t, s, n); +#ifndef WITH_LEANER + if (soap->fpreparesend) + return soap->error = soap->fpreparesend(soap, s, n); +#endif + return SOAP_OK; + } +#ifndef WITH_LEANER + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) + { char t[16]; + sprintf(t, "\r\n%lX\r\n" + (soap->chunksize ? 0 : 2), (unsigned long)n); + DBGMSG(SENT, t, strlen(t)); + if ((soap->error = soap->fsend(soap, t, strlen(t)))) + return soap->error; + soap->chunksize += n; + } + DBGMSG(SENT, s, n); +#endif + return soap->error = soap->fsend(soap, s, n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send(struct soap *soap, const char *s) +{ if (s) + return soap_send_raw(soap, s, strlen(s)); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send2(struct soap *soap, const char *s1, const char *s2) +{ if (soap_send(soap, s1)) + return soap->error; + return soap_send(soap, s2); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send3(struct soap *soap, const char *s1, const char *s2, const char *s3) +{ if (soap_send(soap, s1) + || soap_send(soap, s2)) + return soap->error; + return soap_send(soap, s3); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static size_t +frecv(struct soap *soap, char *s, size_t n) +{ register int r; +#ifdef PALM + register int timeouts = 10; +#endif + soap->errnum = 0; +#if defined(__cplusplus) && !defined(WITH_LEAN) + if (soap->is) + { if (soap->is->good()) + return soap->is->read(s, n).gcount(); + return 0; + } +#endif + if (soap_valid_socket(soap->socket)) + { for (;;) + { +#ifdef WITH_OPENSSL + register int err = 0; +#endif +#ifndef WITH_LEAN + if (soap->recv_timeout) + { struct timeval timeout; + fd_set fd; + if (soap->recv_timeout > 0) + { timeout.tv_sec = soap->recv_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->recv_timeout/1000000; + timeout.tv_usec = -soap->recv_timeout%1000000; + } +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + { soap->error = SOAP_FD_EXCEEDED; + return 0; /* Hint: MUST increase FD_SETSIZE */ + } +#endif + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->socket, &fd); + for (;;) + { +#ifdef WITH_OPENSSL + if (soap->ssl) + r = select((SOAP_SOCKET)(soap->socket + 1), &fd, &fd, &fd, &timeout); + else + r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout); +#else + r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout); +#endif + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + return 0; + } + r = soap_socket_errno(soap->socket); + if (r != SOAP_EINTR && r != SOAP_EAGAIN) + { soap->errnum = r; + return 0; + } + } + } +#endif +#ifdef WITH_OPENSSL + if (soap->ssl) + { r = SSL_read(soap->ssl, s, n); + if (r > 0) + return (size_t)r; + err = SSL_get_error(soap->ssl, r); + if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) + return 0; + } + else if (soap->bio) + { r = BIO_read(soap->bio, s, n); + if (r > 0) + return (size_t)r; + return 0; + } + else +#endif + { +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + { SOAP_SOCKLEN_T k = (SOAP_SOCKLEN_T)sizeof(soap->peer); + memset((void*)&soap->peer, 0, sizeof(soap->peer)); + r = recvfrom((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags, (struct sockaddr*)&soap->peer, &k); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */ + soap->peerlen = (size_t)k; +#ifndef WITH_IPV6 + soap->ip = ntohl(soap->peer.sin_addr.s_addr); +#endif + } + else +#endif + r = recv((SOAP_SOCKET)soap->socket, s, n, soap->socket_flags); +#ifdef PALM + /* CycleSyncDisplay(curStatusMsg); */ +#endif + if (r >= 0) + return (size_t)r; + r = soap_socket_errno(soap->socket); + if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK) + { soap->errnum = r; + return 0; + } + } +#ifndef WITH_LEAN + { struct timeval timeout; + fd_set fd; + if (soap->recv_timeout > 0) + { timeout.tv_sec = soap->recv_timeout; + timeout.tv_usec = 0; + } + else if (soap->recv_timeout < 0) + { timeout.tv_sec = -soap->recv_timeout/1000000; + timeout.tv_usec = -soap->recv_timeout%1000000; + } + else + { timeout.tv_sec = 0; + timeout.tv_usec = 10000; + } +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + { soap->error = SOAP_FD_EXCEEDED; + return 0; /* Hint: MUST increase FD_SETSIZE */ + } +#endif + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->socket, &fd); +#ifdef WITH_OPENSSL + if (soap->ssl && err == SSL_ERROR_WANT_WRITE) + r = select((SOAP_SOCKET)(soap->socket + 1), NULL, &fd, &fd, &timeout); + else + r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout); +#else + r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout); +#endif + if (r < 0 && (r = soap_socket_errno(soap->socket)) != SOAP_EINTR) + { soap->errnum = r; + return 0; + } + if (!r && soap->recv_timeout) + { soap->errnum = 0; + return 0; + } + } +#endif +#ifdef PALM + r = soap_socket_errno(soap->socket); + if (r != SOAP_EINTR && timeouts-- <= 0) + { soap->errnum = r; + return 0; + } +#endif + } + } +#ifdef WITH_FASTCGI + return fread(s, 1, n, stdin); +#else +#ifdef UNDER_CE + return fread(s, 1, n, soap->recvfd); +#else +#ifdef WMW_RPM_IO + if (soap->rpmreqid) + r = httpBlockRead(soap->rpmreqid, s, n); + else +#endif + r = read((SOAP_SOCKET)soap->recvfd, s, n); + if (r >= 0) + return (size_t)r; + soap->errnum = soap_errno; + return 0; +#endif +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +#ifndef WITH_NOIO +#ifndef PALM_1 +static size_t +frecv_stop(struct soap *soap, char *s, size_t n) +{ return 0; +} +#endif +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static soap_wchar +soap_getchunkchar(struct soap *soap) +{ if (soap->bufidx < soap->buflen) + return soap->buf[soap->bufidx++]; + soap->bufidx = 0; + soap->buflen = soap->chunkbuflen = soap->frecv(soap, soap->buf, SOAP_BUFLEN); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket %d\n", (unsigned int)soap->buflen, soap->socket)); + DBGMSG(RECV, soap->buf, soap->buflen); + if (soap->buflen) + return soap->buf[soap->bufidx++]; + return EOF; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +soap_isxdigit(int c) +{ return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv_raw(struct soap *soap) +{ register size_t ret; +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { if (soap->d_stream.next_out == Z_NULL) + return EOF; + if (soap->d_stream.avail_in || !soap->d_stream.avail_out) + { register int r; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflating\n")); + soap->d_stream.next_out = (Byte*)soap->buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + r = inflate(&soap->d_stream, Z_NO_FLUSH); + if (r == Z_OK || r == Z_STREAM_END) + { soap->bufidx = 0; + ret = soap->buflen = SOAP_BUFLEN - soap->d_stream.avail_out; + if (soap->zlib_in == SOAP_ZLIB_GZIP) + soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)ret); + if (r == Z_STREAM_END) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out)); + soap->z_ratio_in = (float)soap->d_stream.total_in / (float)soap->d_stream.total_out; + soap->d_stream.next_out = Z_NULL; + } + if (ret) + { soap->count += ret; + DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- decompressed ----\n")); + DBGMSG(RECV, soap->buf, ret); + return SOAP_OK; + } + } + else if (r != Z_BUF_ERROR) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate error: %s\n", soap->d_stream.msg?soap->d_stream.msg:"")); + soap->d_stream.next_out = Z_NULL; + soap->error = SOAP_ZLIB_ERROR; + return EOF; + } + } +zlib_again: + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK && !soap->chunksize) + { memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN); + soap->buflen = soap->z_buflen; + } + DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- compressed ----\n")); + } +#endif +#ifndef WITH_NOHTTP + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) /* read HTTP chunked transfer */ + { +chunk_again: + if (soap->chunksize) + { soap->buflen = ret = soap->frecv(soap, soap->buf, soap->chunksize > SOAP_BUFLEN ? SOAP_BUFLEN : soap->chunksize); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk: read %u bytes\n", (unsigned int)ret)); + DBGMSG(RECV, soap->buf, ret); + soap->bufidx = 0; + soap->chunksize -= ret; + } + else + { register soap_wchar c; + char *t, tmp[8]; + t = tmp; + if (!soap->chunkbuflen) + { soap->chunkbuflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes (chunked) from socket %d\n", (unsigned int)ret, soap->socket)); + DBGMSG(RECV, soap->buf, ret); + soap->bufidx = 0; + if (!ret) + return soap->ahead = EOF; + } + else + soap->bufidx = soap->buflen; + soap->buflen = soap->chunkbuflen; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk size (idx=%u len=%u)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen)); + while (!soap_isxdigit((int)(c = soap_getchunkchar(soap)))) + { if ((int)c == EOF) + return soap->ahead = EOF; + } + do + *t++ = (char)c; + while (soap_isxdigit((int)(c = soap_getchunkchar(soap))) && t - tmp < 7); + while ((int)c != EOF && c != '\n') + c = soap_getchunkchar(soap); + if ((int)c == EOF) + return soap->ahead = EOF; + *t = '\0'; + soap->chunksize = soap_strtoul(tmp, &t, 16); + if (!soap->chunksize) + { soap->chunkbuflen = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of chunked message\n")); + while ((int)c != EOF && c != '\n') + c = soap_getchunkchar(soap); + return soap->ahead = EOF; + } + soap->buflen = soap->bufidx + soap->chunksize; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving buf len to idx=%u len=%u (%s)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen, tmp)); + if (soap->buflen > soap->chunkbuflen) + { soap->buflen = soap->chunkbuflen; + soap->chunksize -= soap->buflen - soap->bufidx; + soap->chunkbuflen = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Passed end of buffer for chunked HTTP (%u bytes left)\n", (unsigned int)(soap->buflen - soap->bufidx))); + } + else if (soap->chunkbuflen) + soap->chunksize = 0; + ret = soap->buflen - soap->bufidx; + if (!ret) + goto chunk_again; + } + } + else +#endif + { soap->bufidx = 0; + soap->buflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket %d\n", (unsigned int)ret, soap->socket)); + DBGMSG(RECV, soap->buf, ret); + } +#ifndef WITH_LEANER + if (soap->fpreparerecv && (soap->error = soap->fpreparerecv(soap, soap->buf, ret))) + return soap->error; +#endif +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { register int r; + memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); + soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx); + soap->d_stream.avail_in = (unsigned int)ret; + soap->d_stream.next_out = (Byte*)soap->buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + r = inflate(&soap->d_stream, Z_NO_FLUSH); + if (r == Z_OK || r == Z_STREAM_END) + { soap->bufidx = 0; + soap->z_buflen = soap->buflen; + soap->buflen = ret = SOAP_BUFLEN - soap->d_stream.avail_out; + if (soap->zlib_in == SOAP_ZLIB_GZIP) + soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %u bytes\n", (unsigned int)ret)); + if (!ret) + goto zlib_again; + if (r == Z_STREAM_END) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out)); + soap->z_ratio_in = (float)soap->d_stream.total_in / (float)soap->d_stream.total_out; + soap->d_stream.next_out = Z_NULL; + } + DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- decompressed ----\n")); + DBGMSG(RECV, soap->buf, ret); + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to inflate: (%d) %s\n", r, soap->d_stream.msg?soap->d_stream.msg:"")); + soap->d_stream.next_out = Z_NULL; + soap->error = SOAP_ZLIB_ERROR; + return EOF; + } + } +#endif + soap->count += ret; + return !ret; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv(struct soap *soap) +{ +#ifndef WITH_LEANER + if (soap->mode & SOAP_ENC_DIME) + { if (soap->dime.buflen) + { char *s; + int i; + unsigned char tmp[12]; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME hdr for chunked DIME is in buffer\n")); + soap->count += soap->dime.buflen - soap->buflen; + soap->buflen = soap->dime.buflen; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Skip padding (%ld bytes)\n", -(long)soap->dime.size&3)); + for (i = -(long)soap->dime.size&3; i > 0; i--) + { soap->bufidx++; + if (soap->bufidx >= soap->buflen) + if (soap_recv_raw(soap)) + return EOF; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME hdr for next chunk\n")); + s = (char*)tmp; + for (i = 12; i > 0; i--) + { *s++ = soap->buf[soap->bufidx++]; + if (soap->bufidx >= soap->buflen) + if (soap_recv_raw(soap)) + return EOF; + } + soap->dime.flags = tmp[0] & 0x7; + soap->dime.size = ((size_t)tmp[8] << 24) | ((size_t)tmp[9] << 16) | ((size_t)tmp[10] << 8) | ((size_t)tmp[11]); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME chunk (%u bytes)\n", (unsigned int)soap->dime.size)); + if (soap->dime.flags & SOAP_DIME_CF) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "More chunking\n")); + soap->dime.chunksize = soap->dime.size; + if (soap->buflen - soap->bufidx >= soap->dime.size) + { soap->dime.buflen = soap->buflen; + soap->buflen = soap->bufidx + soap->dime.chunksize; + } + else + soap->dime.chunksize -= soap->buflen - soap->bufidx; + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Last chunk\n")); + soap->dime.buflen = 0; + soap->dime.chunksize = 0; + } + soap->count = soap->buflen - soap->bufidx; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%u bytes remaining\n", (unsigned int)soap->count)); + return SOAP_OK; + } + if (soap->dime.chunksize) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get next DIME hdr for chunked DIME (%u bytes chunk)\n", (unsigned int)soap->dime.chunksize)); + if (soap_recv_raw(soap)) + return EOF; + if (soap->buflen - soap->bufidx >= soap->dime.chunksize) + { soap->dime.buflen = soap->buflen; + soap->count -= soap->buflen - soap->bufidx - soap->dime.chunksize; + soap->buflen = soap->bufidx + soap->dime.chunksize; + } + else + soap->dime.chunksize -= soap->buflen - soap->bufidx; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%lu bytes remaining, count=%u\n", (unsigned long)(soap->buflen-soap->bufidx), (unsigned int)soap->count)); + return SOAP_OK; + } + } +#endif + return soap_recv_raw(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +soap_wchar +SOAP_FMAC2 +soap_getchar(struct soap *soap) +{ register soap_wchar c; + c = soap->ahead; + if (c) + { if (c != EOF) + soap->ahead = 0; + return c; + } + return soap_get1(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +const struct soap_code_map* +SOAP_FMAC2 +soap_code(const struct soap_code_map *code_map, const char *str) +{ if (code_map && str) + { while (code_map->string) + { if (!strcmp(str, code_map->string)) /* case sensitive */ + return code_map; + code_map++; + } + } + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +long +SOAP_FMAC2 +soap_code_int(const struct soap_code_map *code_map, const char *str, long other) +{ if (code_map) + { while (code_map->string) + { if (!soap_tag_cmp(str, code_map->string)) /* case insensitive */ + return code_map->code; + code_map++; + } + } + return other; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_code_str(const struct soap_code_map *code_map, long code) +{ if (!code_map) + return NULL; + while (code_map->code != code && code_map->string) + code_map++; + return code_map->string; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +long +SOAP_FMAC2 +soap_code_bits(const struct soap_code_map *code_map, const char *str) +{ register long bits = 0; + if (code_map) + { while (str && *str) + { const struct soap_code_map *p; + for (p = code_map; p->string; p++) + { register size_t n = strlen(p->string); + if (!strncmp(p->string, str, n) && soap_blank(str[n])) + { bits |= p->code; + str += n; + while (*str > 0 && *str <= 32) + str++; + break; + } + } + if (!p->string) + return 0; + } + } + return bits; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_code_list(struct soap *soap, const struct soap_code_map *code_map, long code) +{ register char *t = soap->tmpbuf; + if (code_map) + { while (code_map->string) + { if (code_map->code & code) + { register const char *s = code_map->string; + if (t != soap->tmpbuf) + *t++ = ' '; + while (*s && t < soap->tmpbuf + sizeof(soap->tmpbuf) - 1) + *t++ = *s++; + if (t == soap->tmpbuf + sizeof(soap->tmpbuf) - 1) + break; + } + code_map++; + } + } + *t = '\0'; + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static soap_wchar +soap_char(struct soap *soap) +{ char tmp[8]; + register int i; + register soap_wchar c; + register char *s = tmp; + for (i = 0; i < 7; i++) + { c = soap_get1(soap); + if (c == ';' || (int)c == EOF) + break; + *s++ = (char)c; + } + *s = '\0'; + if (*tmp == '#') + { if (tmp[1] == 'x' || tmp[1] == 'X') + return soap_strtol(tmp + 2, NULL, 16); + return atol(tmp + 1); + } + if (!strcmp(tmp, "lt")) + return '<'; + if (!strcmp(tmp, "gt")) + return '>'; + if (!strcmp(tmp, "amp")) + return '&'; + if (!strcmp(tmp, "quot")) + return '"'; + if (!strcmp(tmp, "apos")) + return '\''; +#ifndef WITH_LEAN + return (soap_wchar)soap_code_int(html_entity_codes, tmp, SOAP_UNKNOWN_CHAR); +#else + return SOAP_UNKNOWN_CHAR; /* use this to represent unknown code */ +#endif +} +#endif + +/******************************************************************************/ +#ifdef WITH_LEAN +#ifndef PALM_1 +soap_wchar +soap_get0(struct soap *soap) +{ if (soap->bufidx >= soap->buflen && soap_recv(soap)) + return EOF; + return (unsigned char)soap->buf[soap->bufidx]; +} +#endif +#endif + +/******************************************************************************/ +#ifdef WITH_LEAN +#ifndef PALM_1 +soap_wchar +soap_get1(struct soap *soap) +{ if (soap->bufidx >= soap->buflen && soap_recv(soap)) + return EOF; + return (unsigned char)soap->buf[soap->bufidx++]; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +soap_wchar +SOAP_FMAC2 +soap_get(struct soap *soap) +{ register soap_wchar c; + c = soap->ahead; + if (c) + { if ((int)c != EOF) + soap->ahead = 0; + } + else + c = soap_get1(soap); + while ((int)c != EOF) + { if (soap->cdata) + { if (c == ']') + { c = soap_get1(soap); + if (c == ']') + { c = soap_get0(soap); + if (c == '>') + { soap->cdata = 0; + soap_get1(soap); + c = soap_get1(soap); + } + else + { soap_unget(soap, ']'); + return ']'; + } + } + else + { soap_revget1(soap); + return ']'; + } + } + else + return c; + } + switch (c) + { case '<': + do c = soap_get1(soap); + while (soap_blank(c)); + if (c == '!' || c == '?' || c == '%') + { register int k = 1; + if (c == '!') + { c = soap_get1(soap); + if (c == '[') + { do c = soap_get1(soap); + while ((int)c != EOF && c != '['); + if ((int)c == EOF) + break; + soap->cdata = 1; + c = soap_get1(soap); + continue; + } + if (c == '-' && (c = soap_get1(soap)) == '-') + { do + { c = soap_get1(soap); + if (c == '-' && (c = soap_get1(soap)) == '-') + break; + } while ((int)c != EOF); + } + } + else if (c == '?') + c = soap_get_pi(soap); + while ((int)c != EOF) + { if (c == '<') + k++; + else if (c == '>') + { if (--k <= 0) + break; + } + c = soap_get1(soap); + } + if ((int)c == EOF) + break; + c = soap_get1(soap); + continue; + } + if (c == '/') + return SOAP_TT; + soap_revget1(soap); + return SOAP_LT; + case '>': + return SOAP_GT; + case '"': + return SOAP_QT; + case '\'': + return SOAP_AP; + case '&': + return soap_char(soap) | 0x80000000; + } + break; + } + return c; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static soap_wchar +soap_get_pi(struct soap *soap) +{ char buf[64]; + register char *s = buf; + register int i = sizeof(buf); + register soap_wchar c = soap_getchar(soap); + /* This is a quick way to parse XML PI and we could use a callback instead to + * enable applications to intercept processing instructions */ + while ((int)c != EOF && c != '?') + { if (--i > 0) + { if (soap_blank(c)) + c = ' '; + *s++ = (char)c; + } + c = soap_getchar(soap); + } + *s = '\0'; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "XML PI \n", buf)); + if (!strncmp(buf, "xml ", 4)) + { s = strstr(buf, " encoding="); + if (s && s[10]) + { if (!soap_tag_cmp(s + 11, "iso-8859-1*") + || !soap_tag_cmp(s + 11, "latin1*")) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to latin1 encoding\n")); + soap->mode |= SOAP_ENC_LATIN; + } + else if (!soap_tag_cmp(s + 11, "utf-8*")) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to utf-8 encoding\n")); + soap->mode &= ~SOAP_ENC_LATIN; + } + } + } + if ((int)c != EOF) + c = soap_getchar(soap); + return c; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_move(struct soap *soap, long n) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving %ld bytes forward\n", (long)n)); + for (; n > 0; n--) + if ((int)soap_getchar(soap) == EOF) + return SOAP_EOF; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_tell(struct soap *soap) +{ return soap->count - soap->buflen + soap->bufidx - (soap->ahead != 0); +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_pututf8(struct soap *soap, register unsigned long c) +{ char tmp[16]; + if (c < 0x80 && c >= 0x20) + { *tmp = (char)c; + return soap_send_raw(soap, tmp, 1); + } +#ifndef WITH_LEAN + if (c >= 0x80 && (soap->mode & SOAP_XML_CANONICAL)) + { register char *t = tmp; + if (c < 0x0800) + *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); + else + { if (c < 0x010000) + *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + else + { if (c < 0x200000) + *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + else + { if (c < 0x04000000) + *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + else + { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + } + *t++ = (char)(0x80 | (c & 0x3F)); + *t = '\0'; + } + else +#endif + sprintf(tmp, "&#%lu;", c); + return soap_send(soap, tmp); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +soap_wchar +SOAP_FMAC2 +soap_getutf8(struct soap *soap) +{ register soap_wchar c, c1, c2, c3, c4; + c = soap->ahead; + if (c > 0xFF) + { soap->ahead = 0; + return c; + } +again: + c = soap_get(soap); + if (c < 0x80 || (soap->mode & SOAP_ENC_LATIN)) + return c; + c1 = soap_get1(soap); + if (c1 < 0x80) + { soap_revget1(soap); /* doesn't look like this is UTF8 */ + return c; + } + c1 &= 0x3F; + if (c < 0xE0) + return ((soap_wchar)(c & 0x1F) << 6) | c1; + c2 = (soap_wchar)soap_get1(soap) & 0x3F; + if (c == 0xEF && c1 == 0x3B && c2 == 0x3F) /* ignore UTF-8 BOM */ + goto again; + if (c < 0xF0) + return ((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2; + c3 = (soap_wchar)soap_get1(soap) & 0x3F; + if (c < 0xF8) + return ((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3; + c4 = (soap_wchar)soap_get1(soap) & 0x3F; + if (c < 0xFC) + return ((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4; + return ((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(soap_get1(soap) & 0x3F); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_puthex(struct soap *soap, const unsigned char *s, int n) +{ char d[2]; + register int i; +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { if (!(soap->dom->data = soap_s2hex(soap, s, NULL, n))) + return soap->error; + return SOAP_OK; + } +#endif + for (i = 0; i < n; i++) + { register int m = *s++; + d[0] = (char)((m >> 4) + (m > 159 ? '7' : '0')); + m &= 0x0F; + d[1] = (char)(m + (m > 9 ? '7' : '0')); + if (soap_send_raw(soap, d, 2)) + return soap->error; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +unsigned char* +SOAP_FMAC2 +soap_gethex(struct soap *soap, int *n) +{ +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { soap->dom->data = soap_string_in(soap, 0, -1, -1); + return (unsigned char*)soap_hex2s(soap, soap->dom->data, NULL, 0, n); + } +#endif +#ifdef WITH_FAST + soap->labidx = 0; + for (;;) + { register char *s; + register int i, k; + if (soap_append_lab(soap, NULL, 0)) + return NULL; + s = soap->labbuf + soap->labidx; + k = soap->lablen - soap->labidx; + soap->labidx = soap->lablen; + for (i = 0; i < k; i++) + { register char d1, d2; + register soap_wchar c; + c = soap_get(soap); + if (soap_isxdigit(c)) + { d1 = (char)c; + c = soap_get(soap); + if (soap_isxdigit(c)) + d2 = (char)c; + else + { soap->error = SOAP_TYPE; + return NULL; + } + } + else + { unsigned char *p; + soap_unget(soap, c); + if (n) + *n = (int)(soap->lablen - k + i); + p = (unsigned char*)soap_malloc(soap, soap->lablen - k + i); + if (p) + memcpy(p, soap->labbuf, soap->lablen - k + i); + return p; + } + *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'); + } + } +#else + if (soap_new_block(soap)) + return NULL; + for (;;) + { register int i; + register char *s = (char*)soap_push_block(soap, SOAP_BLKLEN); + if (!s) + { soap_end_block(soap); + return NULL; + } + for (i = 0; i < SOAP_BLKLEN; i++) + { register char d1, d2; + register soap_wchar c = soap_get(soap); + if (soap_isxdigit(c)) + { d1 = (char)c; + c = soap_get(soap); + if (soap_isxdigit(c)) + d2 = (char)c; + else + { soap_end_block(soap); + soap->error = SOAP_TYPE; + return NULL; + } + } + else + { unsigned char *p; + soap_unget(soap, c); + if (n) + *n = soap_size_block(soap, i); + p = (unsigned char*)soap_save_block(soap, NULL, 0); + return p; + } + *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'); + } + } +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putbase64(struct soap *soap, const unsigned char *s, int n) +{ register int i; + register unsigned long m; + char d[4]; + if (!s) + return SOAP_OK; +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { if (!(soap->dom->data = soap_s2base64(soap, s, NULL, n))) + return soap->error; + return SOAP_OK; + } +#endif + for (; n > 2; n -= 3, s += 3) + { m = s[0]; + m = (m << 8) | s[1]; + m = (m << 8) | s[2]; + for (i = 4; i > 0; m >>= 6) + d[--i] = soap_base64o[m & 0x3F]; + if (soap_send_raw(soap, d, 4)) + return soap->error; + } + if (n > 0) + { m = 0; + for (i = 0; i < n; i++) + m = (m << 8) | *s++; + for (; i < 3; i++) + m <<= 8; + for (i++; i > 0; m >>= 6) + d[--i] = soap_base64o[m & 0x3F]; + for (i = 3; i > n; i--) + d[i] = '='; + if (soap_send_raw(soap, d, 4)) + return soap->error; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +unsigned char* +SOAP_FMAC2 +soap_getbase64(struct soap *soap, int *n, int malloc_flag) +{ +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { soap->dom->data = soap_string_in(soap, 0, -1, -1); + return (unsigned char*)soap_base642s(soap, soap->dom->data, NULL, 0, n); + } +#endif +#ifdef WITH_FAST + soap->labidx = 0; + for (;;) + { register int i, k; + register char *s; + if (soap_append_lab(soap, NULL, 2)) + return NULL; + s = soap->labbuf + soap->labidx; + k = soap->lablen - soap->labidx; + soap->labidx = 3 * (soap->lablen / 3); + if (!s) + return NULL; + for (i = 0; i < k - 2; i += 3) + { register unsigned long m = 0; + register int j = 0; + do + { register soap_wchar c = soap_get(soap); + if (c == '=' || c < 0) + { unsigned char *p; + switch (j) + { case 2: + *s++ = (char)((m >> 4) & 0xFF); + i++; + break; + case 3: + *s++ = (char)((m >> 10) & 0xFF); + *s++ = (char)((m >> 2) & 0xFF); + i += 2; + } + if (n) + *n = (int)(soap->lablen - k + i); + p = (unsigned char*)soap_malloc(soap, soap->lablen - k + i); + if (p) + memcpy(p, soap->labbuf, soap->lablen - k + i); + if (c >= 0) + { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT) + ; + } + soap_unget(soap, c); + return p; + } + c -= '+'; + if (c >= 0 && c <= 79) + { int b = soap_base64i[c]; + if (b >= 64) + { soap->error = SOAP_TYPE; + return NULL; + } + m = (m << 6) + b; + j++; + } + else if (!soap_blank(c + '+')) + { soap->error = SOAP_TYPE; + return NULL; + } + } while (j < 4); + *s++ = (char)((m >> 16) & 0xFF); + *s++ = (char)((m >> 8) & 0xFF); + *s++ = (char)(m & 0xFF); + } + } +#else + if (soap_new_block(soap)) + return NULL; + for (;;) + { register int i; + register char *s = (char*)soap_push_block(soap, 3 * SOAP_BLKLEN); /* must be multiple of 3 */ + if (!s) + { soap_end_block(soap); + return NULL; + } + for (i = 0; i < SOAP_BLKLEN; i++) + { register unsigned long m = 0; + register int j = 0; + do + { register soap_wchar c = soap_get(soap); + if (c == '=' || c < 0) + { unsigned char *p; + i *= 3; + switch (j) + { case 2: + *s++ = (char)((m >> 4) & 0xFF); + i++; + break; + case 3: + *s++ = (char)((m >> 10) & 0xFF); + *s++ = (char)((m >> 2) & 0xFF); + i += 2; + } + if (n) + *n = (int)soap_size_block(soap, i); + p = (unsigned char*)soap_save_block(soap, NULL, 0); + if (c >= 0) + { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT) + ; + } + soap_unget(soap, c); + return p; + } + c -= '+'; + if (c >= 0 && c <= 79) + { int b = soap_base64i[c]; + if (b >= 64) + { soap->error = SOAP_TYPE; + return NULL; + } + m = (m << 6) + b; + j++; + } + else if (!soap_blank(c)) + { soap->error = SOAP_TYPE; + return NULL; + } + } while (j < 4); + *s++ = (char)((m >> 16) & 0xFF); + *s++ = (char)((m >> 8) & 0xFF); + *s++ = (char)(m & 0xFF); + } + } +#endif +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_xop_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options) +{ /* Check MTOM xop:Include element (within hex/base64Binary) */ + /* TODO: this code to be obsoleted with new import/xop.h conventions */ + int body = soap->body; /* should save type too? */ + if (!soap_peek_element(soap)) + { if (!soap_element_begin_in(soap, "xop:Include", 0, NULL) && *soap->href) + { if (soap_dime_forward(soap, ptr, size, id, type, options)) + return soap->error; + } + if (soap->body && soap_element_end_in(soap, NULL)) + return soap->error; + } + soap->body = body; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_dime_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options) +{ struct soap_xlist *xp = (struct soap_xlist*)SOAP_MALLOC(soap, sizeof(struct soap_xlist)); + *ptr = NULL; + *size = 0; + *id = soap_strdup(soap, soap->href); + *type = NULL; + *options = NULL; + if (!xp) + return soap->error = SOAP_EOM; + xp->next = soap->xlist; + xp->ptr = ptr; + xp->size = size; + xp->id = *id; + xp->type = type; + xp->options = options; + soap->xlist = xp; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_strdup(struct soap *soap, const char *s) +{ char *t = NULL; + if (s && (t = (char*)soap_malloc(soap, strlen(s) + 1))) + strcpy(t, s); + return t; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_new_block(struct soap *soap) +{ struct soap_blist *p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New block sequence (prev=%p)\n", soap->blist)); + if (!(p = (struct soap_blist*)SOAP_MALLOC(soap, sizeof(struct soap_blist)))) + return SOAP_EOM; + p->next = soap->blist; + p->ptr = NULL; + p->size = 0; + soap->blist = p; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_push_block(struct soap *soap, size_t n) +{ char *p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push block of %u bytes (%u bytes total)\n", (unsigned int)n, (unsigned int)soap->blist->size + (unsigned int)n)); + if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(char*) + sizeof(size_t)))) + { soap->error = SOAP_EOM; + return NULL; + } + *(char**)p = soap->blist->ptr; + *(size_t*)(p + sizeof(char*)) = n; + soap->blist->ptr = p; + soap->blist->size += n; + return p + sizeof(char*) + sizeof(size_t); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_pop_block(struct soap *soap) +{ char *p; + if (!soap->blist->ptr) + return; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop block\n")); + p = soap->blist->ptr; + soap->blist->size -= *(size_t*)(p + sizeof(char*)); + soap->blist->ptr = *(char**)p; + SOAP_FREE(soap, p); +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static void +soap_update_ptrs(struct soap *soap, char *start, char *end, char *p1, char *p2) +{ int i; + register struct soap_ilist *ip; + register struct soap_flist *fp; +#ifndef WITH_LEANER + register struct soap_xlist *xp; +#endif + register void *p, **q; + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { if (ip->ptr && (char*)ip->ptr >= start && (char*)ip->ptr < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", ip->id, ip->ptr, (char*)ip->ptr + (p1-p2))); + ip->ptr = (char*)ip->ptr + (p1-p2); + } + for (q = &ip->link; q; q = (void**)p) + { p = *q; + if (p && (char*)p >= start && (char*)p < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Link update id='%s' %p\n", ip->id, p)); + *q = (char*)p + (p1-p2); + } + } + for (q = &ip->copy; q; q = (void**)p) + { p = *q; + if (p && (char*)p >= start && (char*)p < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy chain update id='%s' %p\n", ip->id, p)); + *q = (char*)p + (p1-p2); + } + } + for (fp = ip->flist; fp; fp = fp->next) + { if ((char*)fp->ptr >= start && (char*)fp->ptr < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy list update id='%s' %p\n", ip->id, fp)); + fp->ptr = (char*)fp->ptr + (p1-p2); + } + } + } + } +#ifndef WITH_LEANER + for (xp = soap->xlist; xp; xp = xp->next) + { if (xp->ptr && (char*)xp->ptr >= start && (char*)xp->ptr < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", xp->id?xp->id:"", xp->ptr, (char*)xp->ptr + (p1-p2))); + xp->ptr = (unsigned char**)((char*)xp->ptr + (p1-p2)); + xp->size = (int*)((char*)xp->size + (p1-p2)); + xp->type = (char**)((char*)xp->type + (p1-p2)); + xp->options = (char**)((char*)xp->options + (p1-p2)); + } + } +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static int +soap_has_copies(struct soap *soap, register const char *start, register const char *end) +{ register int i; + register struct soap_ilist *ip; + register struct soap_flist *fp; + register const char *p; + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { for (p = (const char*)ip->copy; p; p = *(const char**)p) + if (p >= start && p < end) + return SOAP_ERR; + for (fp = ip->flist; fp; fp = fp->next) + if ((const char*)fp->ptr >= start && (const char*)fp->ptr < end) + return SOAP_ERR; + } + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_resolve(struct soap *soap) +{ register int i; + register struct soap_ilist *ip; + register struct soap_flist *fp; + short flag; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data\n")); + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { if (ip->ptr) + { register void *p, **q, *r; + q = (void**)ip->link; + ip->link = NULL; + r = ip->ptr; + DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing link chain to resolve id='%s'\n", ip->id)); + while (q) + { p = *q; + *q = r; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "... link %p -> %p\n", q, r)); + q = (void**)p; + } + } + else if (*ip->id == '#') + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Missing data for id='%s'\n", ip->id)); + strcpy(soap->id, ip->id + 1); + return soap->error = SOAP_MISSING_ID; + } + } + } + do + { flag = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution phase\n")); + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { if (ip->ptr && !soap_has_copies(soap, (const char*)ip->ptr, (const char*)ip->ptr + ip->size)) + { if (ip->copy) + { register void *p, **q = (void**)ip->copy; + DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing copy chain to resolve id='%s'\n", ip->id)); + ip->copy = NULL; + do + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... copy %p -> %p (%u bytes)\n", ip->ptr, q, (unsigned int)ip->size)); + p = *q; + memcpy(q, ip->ptr, ip->size); + q = (void**)p; + } while (q); + flag = 1; + } + for (fp = ip->flist; fp; fp = ip->flist) + { register unsigned int k = fp->level; + register void *p = ip->ptr; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data type=%d location=%p level=%u,%u id='%s'\n", ip->type, p, ip->level, fp->level, ip->id)); + while (ip->level < k) + { register void **q = (void**)soap_malloc(soap, sizeof(void*)); + if (!q) + return soap->error; + *q = p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level, new location=%p holds=%p...\n", q, *q)); + p = (void*)q; + k--; + } + if (fp->fcopy) + fp->fcopy(soap, ip->type, fp->type, fp->ptr, fp->len, p, ip->size); + else + soap_fcopy(soap, ip->type, fp->type, fp->ptr, fp->len, p, ip->size); + ip->flist = fp->next; + SOAP_FREE(soap, fp); + flag = 1; + } + } + } + } + } while (flag); +#ifdef SOAP_DEBUG + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { if (ip->copy || ip->flist) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution error: forwarded data for id='%s' could not be propagated, please report this problem to the developers\n", ip->id)); + } + } + } +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution done\n")); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_size_block(struct soap *soap, size_t n) +{ if (soap->blist->ptr) + { soap->blist->size -= *(size_t*)(soap->blist->ptr + sizeof(char*)) - n; + *(size_t*)(soap->blist->ptr + sizeof(char*)) = n; + } + return soap->blist->size; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_first_block(struct soap *soap) +{ char *p, *q, *r; + p = soap->blist->ptr; + if (!p) + return NULL; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "First block\n")); + r = NULL; + do + { q = *(char**)p; + *(char**)p = r; + r = p; + p = q; + } while (p); + soap->blist->ptr = r; + return r + sizeof(char*) + sizeof(size_t); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_next_block(struct soap *soap) +{ char *p; + p = soap->blist->ptr; + if (p) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Next block\n")); + soap->blist->ptr = *(char**)p; + SOAP_FREE(soap, p); + if (soap->blist->ptr) + return soap->blist->ptr + sizeof(char*) + sizeof(size_t); + } + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_block_size(struct soap *soap) +{ return *(size_t*)(soap->blist->ptr + sizeof(char*)); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_end_block(struct soap *soap) +{ struct soap_blist *bp; + char *p, *q; + bp = soap->blist; + if (bp) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of block sequence, free all remaining blocks\n")); + for (p = bp->ptr; p; p = q) + { q = *(char**)p; + SOAP_FREE(soap, p); + } + soap->blist = bp->next; + SOAP_FREE(soap, bp); + } + DBGLOG(TEST, if (soap->blist) SOAP_MESSAGE(fdebug, "Restore previous block sequence\n")); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_save_block(struct soap *soap, char *p, int flag) +{ register size_t n; + register char *q, *s; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Save all blocks in contiguous memory space of %u bytes (%p->%p)\n", (unsigned int)soap->blist->size, soap->blist->ptr, p)); + if (soap->blist->size) + { if (!p) + p = (char*)soap_malloc(soap, soap->blist->size); + if (p) + { for (s = p, q = soap_first_block(soap); q; q = soap_next_block(soap)) + { n = soap_block_size(soap); +#ifndef WITH_NOIDREF + if (flag) + soap_update_ptrs(soap, q, q + n, s, q); +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy %u bytes from %p to %p\n", (unsigned int)n, q, s)); + memcpy(s, q, n); + s += n; + } + } + else + soap->error = SOAP_EOM; + } + soap_end_block(soap); + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putsize(struct soap *soap, const char *type, int size) +{ return soap_putsizes(soap, type, &size, 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putsizes(struct soap *soap, const char *type, const int *size, int dim) +{ return soap_putsizesoffsets(soap, type, size, NULL, dim); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putsizesoffsets(struct soap *soap, const char *type, const int *size, const int *offset, int dim) +{ int i; + if (!type) + return NULL; + if (soap->version == 2) + { sprintf(soap->type, "%s[%d", type, size[0]); + for (i = 1; i < dim; i++) + sprintf(soap->type + strlen(soap->type), " %d", size[i]); + } + else + { if (offset) + { sprintf(soap->type, "%s[%d", type, size[0] + offset[0]); + for (i = 1; i < dim; i++) + sprintf(soap->type + strlen(soap->type), ",%d", size[i] + offset[i]); + } + else + { sprintf(soap->type, "%s[%d", type, size[0]); + for (i = 1; i < dim; i++) + sprintf(soap->type + strlen(soap->type), ",%d", size[i]); + } + strcat(soap->type, "]"); + } + return soap->type; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putoffset(struct soap *soap, int offset) +{ return soap_putoffsets(soap, &offset, 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putoffsets(struct soap *soap, const int *offset, int dim) +{ register int i; + sprintf(soap->arrayOffset, "[%d", offset[0]); + for (i = 1; i < dim; i++) + sprintf(soap->arrayOffset + strlen(soap->arrayOffset), ",%d", offset[i]); + strcat(soap->arrayOffset, "]"); + return soap->arrayOffset; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_size(const int *size, int dim) +{ register int i, n = size[0]; + for (i = 1; i < dim; i++) + n *= size[i]; + return n; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getoffsets(const char *attr, const int *size, int *offset, int dim) +{ register int i, j = 0; + if (offset) + for (i = 0; i < dim && attr && *attr; i++) + { attr++; + j *= size[i]; + j += offset[i] = (int)atol(attr); + attr = strchr(attr, ','); + } + else + for (i = 0; i < dim && attr && *attr; i++) + { attr++; + j *= size[i]; + j += (int)atol(attr); + attr = strchr(attr, ','); + } + return j; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getsize(const char *attr1, const char *attr2, int *j) +{ register int n, k; + char *s; + *j = 0; + if (!*attr1) + return -1; + if (*attr1 == '[') + attr1++; + n = 1; + for (;;) + { k = (int)soap_strtol(attr1, &s, 10); + n *= k; + if (k < 0 || n > SOAP_MAXARRAYSIZE || s == attr1) + return -1; + attr1 = strchr(s, ','); + if (!attr1) + attr1 = strchr(s, ' '); + if (attr2 && *attr2) + { attr2++; + *j *= k; + k = (int)soap_strtol(attr2, &s, 10); + *j += k; + if (k < 0) + return -1; + attr2 = s; + } + if (!attr1) + break; + attr1++; + } + return n - *j; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getsizes(const char *attr, int *size, int dim) +{ register int i, k, n; + if (!*attr) + return -1; + i = strlen(attr); + n = 1; + do + { for (i = i-1; i >= 0; i--) + if (attr[i] == '[' || attr[i] == ',' || attr[i] == ' ') + break; + k = (int)atol(attr + i + 1); + n *= size[--dim] = k; + if (k < 0 || n > SOAP_MAXARRAYSIZE) + return -1; + } while (i >= 0 && attr[i] != '['); + return n; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getposition(const char *attr, int *pos) +{ register int i, n; + if (!*attr) + return -1; + n = 0; + i = 1; + do + { pos[n++] = (int)atol(attr + i); + while (attr[i] && attr[i] != ',' && attr[i] != ']') + i++; + if (attr[i] == ',') + i++; + } while (n < SOAP_MAXDIMS && attr[i] && attr[i] != ']'); + return n; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_push_namespace(struct soap *soap, const char *id, const char *ns) +{ register struct soap_nlist *np; + register struct Namespace *p; + register short i = -1; + register size_t n, k; + n = strlen(id); + k = strlen(ns) + 1; + p = soap->local_namespaces; + if (p) + { for (i = 0; p->id; p++, i++) + { if (p->ns && !strcmp(ns, p->ns)) + { if (p->out) + { SOAP_FREE(soap, p->out); + p->out = NULL; + } + break; + } + if (p->out) + { if (!strcmp(ns, p->out)) + break; + } + else if (p->in) + { if (!soap_tag_cmp(ns, p->in)) + { if ((p->out = (char*)SOAP_MALLOC(soap, k))) + strcpy(p->out, ns); + break; + } + } + } + if (!p || !p->id) + i = -1; + } + if (i >= 0) + k = 0; + np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k); + if (!np) + return soap->error = SOAP_EOM; + np->next = soap->nlist; + soap->nlist = np; + np->level = soap->level; + np->index = i; + strcpy(np->id, id); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push namespace binding (level=%u) '%s' '%s'\n", soap->level, id, ns)); + if (i < 0) + { np->ns = np->id + n + 1; + strcpy(np->ns, ns); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push NOT OK: no match found for '%s' in namespace mapping table (added to stack anyway)\n", ns)); + } + else + { np->ns = NULL; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push OK ('%s' matches '%s' in namespace table)\n", id, p->id)); + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_pop_namespace(struct soap *soap) +{ register struct soap_nlist *np; + while (soap->nlist && soap->nlist->level >= soap->level) + { np = soap->nlist->next; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Popped namespace binding (level=%u) '%s'\n", soap->level, soap->nlist->id)); + SOAP_FREE(soap, soap->nlist); + soap->nlist = np; + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_match_namespace(struct soap *soap, const char *id1, const char *id2, int n1, int n2) +{ register struct soap_nlist *np = soap->nlist; + while (np && (strncmp(np->id, id1, n1) || np->id[n1])) + np = np->next; + if (np) + { if (np->index < 0 + || (soap->local_namespaces[np->index].id + && (strncmp(soap->local_namespaces[np->index].id, id2, n2) + || soap->local_namespaces[np->index].id[n2]))) + return SOAP_NAMESPACE; + return SOAP_OK; + } + if (n1 == 3 && n1 == n2 && !strcmp(id1, "xml") && !strcmp(id1, id2)) + return SOAP_OK; + return soap->error = SOAP_SYNTAX_ERROR; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_current_namespace(struct soap *soap, const char *tag) +{ register struct soap_nlist *np; + register const char *s; + np = soap->nlist; + if (!(s = strchr(tag, ':'))) + { while (np && *np->id) /* find default namespace, if present */ + np = np->next; + } + else + { while (np && (strncmp(np->id, tag, s - tag) || np->id[s - tag])) + np = np->next; + if (!np) + soap->error = SOAP_NAMESPACE; + } + if (np) + { if (np->index >= 0) + return soap->namespaces[np->index].ns; + if (np->ns) + return soap_strdup(soap, np->ns); + } + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_tag_cmp(const char *s, const char *t) +{ for (;;) + { register int c1 = *s; + register int c2 = *t; + if (!c1 || c1 == '"') + break; + if (c2 != '-') + { if (c1 != c2) + { if (c1 >= 'A' && c1 <= 'Z') + c1 += 'a' - 'A'; + if (c2 >= 'A' && c2 <= 'Z') + c2 += 'a' - 'A'; + } + if (c1 != c2) + { if (c2 != '*') + return 1; + c2 = *++t; + if (!c2) + return 0; + if (c2 >= 'A' && c2 <= 'Z') + c2 += 'a' - 'A'; + for (;;) + { c1 = *s; + if (!c1 || c1 == '"') + break; + if (c1 >= 'A' && c1 <= 'Z') + c1 += 'a' - 'A'; + if (c1 == c2 && !soap_tag_cmp(s + 1, t + 1)) + return 0; + s++; + } + break; + } + } + s++; + t++; + } + if (*t == '*' && !t[1]) + return 0; + return *t; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_match_tag(struct soap *soap, const char *tag1, const char *tag2) +{ register const char *s, *t; + register int err; + if (!tag1 || !tag2 || !*tag2) + return SOAP_OK; + s = strchr(tag1, ':'); + t = strchr(tag2, ':'); + if (t) + { if (s) + { if (t[1] && SOAP_STRCMP(s + 1, t + 1)) + return SOAP_TAG_MISMATCH; + if (t != tag2 && (err = soap_match_namespace(soap, tag1, tag2, s - tag1, t - tag2))) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2)); + if (err == SOAP_NAMESPACE) + return SOAP_TAG_MISMATCH; + return err; + } + } + else if (SOAP_STRCMP(tag1, t + 1)) + return SOAP_TAG_MISMATCH; + else if (t != tag2 && (err = soap_match_namespace(soap, tag1, tag2, 0, t - tag2))) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2)); + if (err == SOAP_NAMESPACE) + return SOAP_TAG_MISMATCH; + return err; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags and (default) namespaces match: '%s' '%s'\n", tag1, tag2)); + return SOAP_OK; + } + if (s) + { if (SOAP_STRCMP(s + 1, tag2)) + return SOAP_TAG_MISMATCH; + } + else if (SOAP_STRCMP(tag1, tag2)) + return SOAP_TAG_MISMATCH; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags match: '%s' '%s'\n", tag1, tag2)); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_match_array(struct soap *soap, const char *type) +{ if (*soap->arrayType) + if (soap_match_tag(soap, soap->arrayType, type) + && soap_match_tag(soap, soap->arrayType, "xsd:anyType") + && soap_match_tag(soap, soap->arrayType, "xsd:ur-type") + ) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array type mismatch: '%s' '%s'\n", soap->arrayType, type)); + return SOAP_TAG_MISMATCH; + } + return SOAP_OK; +} +#endif + +/******************************************************************************\ + * + * SSL + * +\******************************************************************************/ + +#ifdef WITH_OPENSSL +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_rand() +{ unsigned char buf[4]; + if (!ssl_init_done) + soap_ssl_init(); + RAND_pseudo_bytes(buf, 4); + return *(int*)buf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_ssl_server_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *password, const char *cafile, const char *capath, const char *dhfile, const char *randfile, const char *sid) +{ int err; + soap->keyfile = keyfile; + soap->password = password; + soap->cafile = cafile; + soap->capath = capath; + soap->dhfile = dhfile; + soap->randfile = randfile; + soap->ssl_flags = flags | (dhfile == NULL ? SOAP_SSL_RSA : 0); + if (!(err = soap->fsslauth(soap))) + { if (sid) + SSL_CTX_set_session_id_context(soap->ctx, (unsigned char*)sid, strlen(sid)); + } + return err; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_ssl_client_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *password, const char *cafile, const char *capath, const char *randfile) +{ soap->keyfile = keyfile; + soap->password = password; + soap->cafile = cafile; + soap->capath = capath; + soap->dhfile = NULL; + soap->ssl_flags = flags; + soap->randfile = randfile; + return soap->fsslauth(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_ssl_init() +{ /* Note: for MT systems, the main program MUST call soap_ssl_init() before any threads are started */ + if (!ssl_init_done) + { ssl_init_done = 1; + SSL_library_init(); +#ifndef WITH_LEAN + SSL_load_error_strings(); +#endif + if (!RAND_load_file("/dev/urandom", 1024)) + { char buf[1024]; + RAND_seed(buf, sizeof(buf)); + while (!RAND_status()) + { int r = rand(); + RAND_seed(&r, sizeof(int)); + } + } + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +const char * +SOAP_FMAC2 +soap_ssl_error(struct soap *soap, int ret) +{ int err = SSL_get_error(soap->ssl, ret); + const char *msg = soap_code_str(h_ssl_error_codes, err); + if (msg) + strcpy(soap->msgbuf, msg); + else + return ERR_error_string(err, soap->msgbuf); + if (ERR_peek_error()) + { unsigned long r; + strcat(soap->msgbuf, "\n"); + while ((r = ERR_get_error())) + ERR_error_string_n(r, soap->msgbuf + strlen(soap->msgbuf), sizeof(soap->msgbuf) - strlen(soap->msgbuf)); + } + else + { switch (ret) + { case 0: + strcpy(soap->msgbuf, "EOF was observed that violates the protocol. The client probably provided invalid authentication information."); + break; + case -1: + sprintf(soap->msgbuf, "Error observed by underlying BIO: %s", strerror(errno)); + break; + } + } + return soap->msgbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +ssl_password(char *buf, int num, int rwflag, void *userdata) +{ if (num < (int)strlen((char*)userdata) + 1) + return 0; + return strlen(strcpy(buf, (char*)userdata)); +} +#endif + +/******************************************************************************/ +/* This callback is included for future references. It should not be deleted +#ifndef PALM_2 +static DH * +ssl_tmp_dh(SSL *ssl, int is_export, int keylength) +{ static DH *dh512 = NULL; + static DH *dh1024 = NULL; + DH *dh; + switch (keylength) + { case 512: + if (!dh512) + { BIO *bio = BIO_new_file("dh512.pem", "r"); + if (bio) + { dh512 = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + return dh512; + } + } + else + return dh512; + default: + if (!dh1024) + { BIO *bio = BIO_new_file("dh1024.pem", "r"); + if (bio) + { dh1024 = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + } + } + dh = dh1024; + } + return dh; +} +#endif +*/ + +/******************************************************************************/ +#ifndef PALM_1 +static int +ssl_auth_init(struct soap *soap) +{ long flags; + int mode; + if (!ssl_init_done) + soap_ssl_init(); + if (!soap->ctx) + { if (!(soap->ctx = SSL_CTX_new(SSLv23_method()))) + return soap_set_receiver_error(soap, "SSL error", "Can't setup context", SOAP_SSL_ERROR); + /* Alters the behavior of SSL read/write: + SSL_CTX_set_mode(soap->ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY); + */ + } + if (soap->randfile) + { if (!RAND_load_file(soap->randfile, -1)) + return soap_set_receiver_error(soap, "SSL error", "Can't load randomness", SOAP_SSL_ERROR); + } + if (soap->cafile || soap->capath) + { if (!SSL_CTX_load_verify_locations(soap->ctx, soap->cafile, soap->capath)) + return soap_set_receiver_error(soap, "SSL error", "Can't read CA file and directory", SOAP_SSL_ERROR); + if (soap->cafile && (soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION)) + SSL_CTX_set_client_CA_list(soap->ctx, SSL_load_client_CA_file(soap->cafile)); + } + if (!SSL_CTX_set_default_verify_paths(soap->ctx)) + return soap_set_receiver_error(soap, "SSL error", "Can't read default CA file and/or directory", SOAP_SSL_ERROR); +/* This code assumes a typical scenario, see alternative code below */ + if (soap->keyfile) + { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile)) + return soap_set_receiver_error(soap, "SSL error", "Can't read certificate key file", SOAP_SSL_ERROR); + if (soap->password) + { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password); + SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password); + } + if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM)) + return soap_set_receiver_error(soap, "SSL error", "Can't read key file", SOAP_SSL_ERROR); + } +/* Suggested alternative approach to check cafile first before the key file: + if (soap->password) + { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password); + SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password); + } + if (!soap->cafile || !SSL_CTX_use_certificate_chain_file(soap->ctx, soap->cafile)) + { if (soap->keyfile) + { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile)) + return soap_set_receiver_error(soap, "SSL error", "Can't read certificate or key file", SOAP_SSL_ERROR); + if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM)) + return soap_set_receiver_error(soap, "SSL error", "Can't read key file", SOAP_SSL_ERROR); + } + } +*/ + if ((soap->ssl_flags & SOAP_SSL_RSA)) + { RSA *rsa = RSA_generate_key(1024, RSA_F4, NULL, NULL); + if (!SSL_CTX_set_tmp_rsa(soap->ctx, rsa)) + { if (rsa) + RSA_free(rsa); + return soap_set_receiver_error(soap, "SSL error", "Can't set RSA key", SOAP_SSL_ERROR); + } + RSA_free(rsa); + } + else if (soap->dhfile) + { DH *dh = 0; + BIO *bio; + bio = BIO_new_file(soap->dhfile, "r"); + if (!bio) + return soap_set_receiver_error(soap, "SSL error", "Can't read DH file", SOAP_SSL_ERROR); + dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + if (SSL_CTX_set_tmp_dh(soap->ctx, dh) < 0) + { if (dh) + DH_free(dh); + return soap_set_receiver_error(soap, "SSL error", "Can't set DH parameters", SOAP_SSL_ERROR); + } + DH_free(dh); + } + flags = (SSL_OP_ALL | SSL_OP_NO_SSLv2); + if ((soap->ssl_flags & SOAP_SSLv3)) + flags |= SSL_OP_NO_TLSv1; + if ((soap->ssl_flags & SOAP_TLSv1)) + flags |= SSL_OP_NO_SSLv3; + SSL_CTX_set_options(soap->ctx, flags); + if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION)) + mode = (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT); + else if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION)) + mode = SSL_VERIFY_PEER; + else + mode = SSL_VERIFY_NONE; + SSL_CTX_set_verify(soap->ctx, mode, soap->fsslverify); +#if (OPENSSL_VERSION_NUMBER < 0x00905100L) + SSL_CTX_set_verify_depth(soap->ctx, 1); +#else + SSL_CTX_set_verify_depth(soap->ctx, 9); +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +ssl_verify_callback(int ok, X509_STORE_CTX *store) +{ +#ifdef SOAP_DEBUG + if (!ok) + { char data[256]; + X509 *cert = X509_STORE_CTX_get_current_cert(store); + fprintf(stderr, "SSL verify error or warning with certificate at depth %d: %s\n", X509_STORE_CTX_get_error_depth(store), X509_verify_cert_error_string(X509_STORE_CTX_get_error(store))); + X509_NAME_oneline(X509_get_issuer_name(cert), data, sizeof(data)); + fprintf(stderr, "certificate issuer %s\n", data); + X509_NAME_oneline(X509_get_subject_name(cert), data, sizeof(data)); + fprintf(stderr, "certificate subject %s\n", data); + } +#endif + /* Note: return 1 to continue, but unsafe progress will be terminated by SSL */ + return ok; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_ssl_accept(struct soap *soap) +{ BIO *bio; + int timeouts, r, s; + if (!soap_valid_socket(soap->socket)) + return soap_set_receiver_error(soap, "SSL error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR); + if (!soap->ctx && (soap->error = soap->fsslauth(soap))) + return SOAP_INVALID_SOCKET; + if (!soap->ssl) + { soap->ssl = SSL_new(soap->ctx); + if (!soap->ssl) + return soap_set_receiver_error(soap, "SSL error", "SSL_new() failed in soap_ssl_accept()", SOAP_SSL_ERROR); + } + else + SSL_clear(soap->ssl); + soap->imode |= SOAP_ENC_SSL; + soap->omode |= SOAP_ENC_SSL; + /* Set SSL sockets to non-blocking */ +#if defined(WIN32) + { u_long nonblocking = 1; + ioctlsocket((SOAP_SOCKET)soap->socket, FIONBIO, &nonblocking); + } +#elif defined(VXWORKS) + { u_long nonblocking = 1; + ioctl((SOAP_SOCKET)soap->socket, FIONBIO, (int)&nonblocking); + } +#else + fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL)|O_NONBLOCK); +#endif + bio = BIO_new_socket((SOAP_SOCKET)soap->socket, BIO_NOCLOSE); + SSL_set_bio(soap->ssl, bio, bio); + timeouts = 100; /* 10 sec retries, 100 times 0.1 sec */ + while ((r = SSL_accept(soap->ssl)) <= 0) + { int err = SSL_get_error(soap->ssl, r); + if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) + { struct timeval timeout; + fd_set fd; + timeout.tv_sec = 0; + timeout.tv_usec = 100000; +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + return SOAP_FD_EXCEEDED; /* Hint: MUST increase FD_SETSIZE */ +#endif + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->socket, &fd); + if (err == SSL_ERROR_WANT_READ) + s = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout); + else + s = select((SOAP_SOCKET)(soap->socket + 1), NULL, &fd, &fd, &timeout); + if (s < 0 && (s = soap_socket_errno(soap->socket)) != SOAP_EINTR) + { soap->errnum = s; + break; + } + } + else + { soap->errnum = err; + break; + } + if (timeouts-- <= 0) + break; + } + if (r <= 0) + { soap_set_receiver_error(soap, soap_ssl_error(soap, r), "SSL_accept() failed in soap_ssl_accept()", SOAP_SSL_ERROR); + soap_closesock(soap); + return SOAP_SSL_ERROR; + } + if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION)) + { X509 *peer; + int err; + if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK) + { soap_closesock(soap); + return soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL certificate presented by peer cannot be verified in soap_ssl_accept()", SOAP_SSL_ERROR); + } + peer = SSL_get_peer_certificate(soap->ssl); + if (!peer) + { soap_closesock(soap); + return soap_set_sender_error(soap, "SSL error", "No SSL certificate was presented by the peer in soap_ssl_accept()", SOAP_SSL_ERROR); + } + X509_free(peer); + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#endif /* WITH_OPENSSL */ + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_init(struct soap *soap) +{ soap->errmode = 1; +#ifdef WIN32 + if (tcp_done) + return 0; + else + { WSADATA w; + if (WSAStartup(MAKEWORD(1, 1), &w)) + return -1; + tcp_done = 1; + } +#endif + return 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_done(struct soap *soap) +{ +#ifdef SOAP_DEBUG + int i; +#endif + if (soap_check_state(soap)) + return; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Done with context\n")); + soap_free_temp(soap); + while (soap->clist) + { struct soap_clist *p = soap->clist->next; + SOAP_FREE(soap, soap->clist); + soap->clist = p; + } + soap->keep_alive = 0; /* to force close the socket */ + soap_closesock(soap); +#ifdef WITH_COOKIES + soap_free_cookies(soap); +#endif + while (soap->plugins) + { register struct soap_plugin *p = soap->plugins->next; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Removing plugin '%s'\n", soap->plugins->id)); + if (soap->plugins->fcopy || soap->state == SOAP_INIT) + soap->plugins->fdelete(soap, soap->plugins); + SOAP_FREE(soap, soap->plugins); + soap->plugins = p; + } + soap->fplugin = fplugin; + soap->fmalloc = NULL; +#ifndef WITH_NOHTTP + soap->fpost = http_post; + soap->fget = http_get; + soap->fform = NULL; + soap->fposthdr = http_post_header; + soap->fresponse = http_response; + soap->fparse = http_parse; + soap->fparsehdr = http_parse_header; +#endif + soap->fheader = NULL; +#ifndef WITH_NOIO +#ifndef WITH_IPV6 + soap->fresolve = tcp_gethost; +#else + soap->fresolve = NULL; +#endif + soap->faccept = tcp_accept; + soap->fopen = tcp_connect; + soap->fclose = tcp_disconnect; + soap->fclosesocket = tcp_closesocket; + soap->fshutdownsocket = tcp_shutdownsocket; + soap->fsend = fsend; + soap->frecv = frecv; + soap->fpoll = soap_poll; +#else + soap->fopen = NULL; + soap->fclose = NULL; + soap->fpoll = NULL; +#endif +#ifndef WITH_LEANER + soap->fprepareinit = NULL; + soap->fpreparesend = NULL; + soap->fpreparerecv = NULL; + soap->fpreparefinal = NULL; +#endif + soap->fseterror = NULL; + soap->fignore = NULL; + soap->fserveloop = NULL; +#ifdef WITH_OPENSSL + if (soap->session) + { SSL_SESSION_free(soap->session); + soap->session = NULL; + } +#endif + if (soap->state == SOAP_INIT) + { if (soap_valid_socket(soap->master)) + { soap->fclosesocket(soap, (SOAP_SOCKET)soap->master); + soap->master = SOAP_INVALID_SOCKET; + } +#ifdef WITH_OPENSSL + if (soap->ctx) + { SSL_CTX_free(soap->ctx); + soap->ctx = NULL; + } +#endif + } +#ifdef SOAP_DEBUG + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free logfiles\n")); + for (i = 0; i < SOAP_MAXLOGS; i++) + { if (soap->logfile[i]) + { SOAP_FREE(soap, (void*)soap->logfile[i]); + soap->logfile[i] = NULL; + } + soap_close_logfile(soap, i); + } + soap_free_mht(soap); + soap->state = 0; +#endif +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_cleanup(struct soap *soap) +{ soap_done(soap); +#ifdef WIN32 + if (!tcp_done) + return; + tcp_done = 0; + WSACleanup(); +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static const char* +tcp_error(struct soap *soap) +{ register const char *msg = NULL; + switch (soap->errmode) + { case 0: + msg = soap_strerror(soap); + break; + case 1: + msg = "WSAStartup failed"; + break; + case 2: + { +#ifndef WITH_LEAN + msg = soap_code_str(h_error_codes, soap->errnum); + if (!msg) +#endif + { sprintf(soap->msgbuf, "TCP/UDP IP error %d", soap->errnum); + msg = soap->msgbuf; + } + } + } + return msg; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static const char* +http_error(struct soap *soap, int status) +{ register const char *msg = SOAP_STR_EOS; +#ifndef WITH_LEAN + msg = soap_code_str(h_http_error_codes, status); + if (!msg) + msg = SOAP_STR_EOS; +#endif + return msg; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_IPV6 +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_gethost(struct soap *soap, const char *addr, struct in_addr *inaddr) +{ soap_int32 iadd = -1; + struct hostent hostent, *host = &hostent; +#ifdef VXWORKS + int hostint; + /* inet_addr(), and hostGetByName() expect "char *"; addr is a "const char *". */ + iadd = inet_addr((char*)addr); +#else +#if defined(_AIXVERSION_431) || defined(TRU64) + struct hostent_data ht_data; +#endif +#ifdef AS400 + iadd = inet_addr((void*)addr); +#else + iadd = inet_addr(addr); +#endif +#endif + if (iadd != -1) + { memcpy(inaddr, &iadd, sizeof(iadd)); + return SOAP_OK; + } +#if defined(__GLIBC__) || defined(FREEBSD) || defined(__FreeBSD__) + if (gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &host, &soap->errnum) < 0) + host = NULL; +#elif defined(_AIXVERSION_431) || defined(TRU64) + memset((void*)&ht_data, 0, sizeof(ht_data)); + if (gethostbyname_r(addr, &hostent, &ht_data) < 0) + { host = NULL; + soap->errnum = h_errno; + } +#elif defined(HAVE_GETHOSTBYNAME_R) + host = gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &soap->errnum); +#elif defined(VXWORKS) + /* If the DNS resolver library resolvLib has been configured in the vxWorks + * image, a query for the host IP address is sent to the DNS server, if the + * name was not found in the local host table. */ + hostint = hostGetByName((char*)addr); + if (hostint == ERROR) + { host = NULL; + soap->errnum = soap_errno; + } +#else +#ifdef AS400 + if (!(host = gethostbyname((void*)addr))) + soap->errnum = h_errno; +#else + if (!(host = gethostbyname(addr))) + soap->errnum = h_errno; +#endif +#endif + if (!host) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Host name not found\n")); + return SOAP_ERR; + } +#ifdef VXWORKS + inaddr->s_addr = hostint; +#else + memcpy(inaddr, host->h_addr, host->h_length); +#endif + return SOAP_OK; +} +#endif +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_connect(struct soap *soap, const char *endpoint, const char *host, int port) +{ +#ifdef WITH_IPV6 + struct addrinfo hints, *res, *ressave; +#endif + register int fd, err = 0; +#ifndef WITH_LEAN + int retry = 10; + int len = SOAP_BUFLEN; + int set = 1; +#endif + if (soap_valid_socket(soap->socket)) + soap->fclosesocket(soap, (SOAP_SOCKET)soap->socket); + soap->socket = SOAP_INVALID_SOCKET; + if (tcp_init(soap)) + { soap->errnum = 0; + soap_set_sender_error(soap, tcp_error(soap), "TCP init failed in tcp_connect()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + soap->errmode = 0; +#ifdef WITH_IPV6 + memset((void*)&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + hints.ai_socktype = SOCK_DGRAM; + else +#endif + hints.ai_socktype = SOCK_STREAM; + soap->errmode = 2; + if (soap->proxy_host) + err = getaddrinfo(soap->proxy_host, soap_int2s(soap, soap->proxy_port), &hints, &res); + else + err = getaddrinfo(host, soap_int2s(soap, port), &hints, &res); + if (err) + { soap_set_sender_error(soap, gai_strerror(err), "getaddrinfo failed in tcp_connect()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + ressave = res; +again: + fd = (int)socket(res->ai_family, res->ai_socktype, res->ai_protocol); + soap->errmode = 0; +#else +again: +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + fd = (int)socket(AF_INET, SOCK_DGRAM, 0); + else +#endif + fd = (int)socket(AF_INET, SOCK_STREAM, 0); +#endif + if (fd < 0) + { soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "socket failed in tcp_connect()", SOAP_TCP_ERROR); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } +#ifdef SOCKET_CLOSE_ON_EXEC +#ifdef WIN32 +#ifndef UNDER_CE + SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0); +#endif +#else + fcntl(fd, F_SETFD, 1); +#endif +#endif +#ifndef WITH_LEAN + if (soap->connect_flags == SO_LINGER) + { struct linger linger; + memset((void*)&linger, 0, sizeof(linger)); + linger.l_onoff = 1; + linger.l_linger = 0; + if (setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger))) + { soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } + } + else if (soap->connect_flags && setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, soap->connect_flags, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "setsockopt failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } + if (soap->keep_alive && setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } + if (setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } + if (setsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } +#ifdef TCP_NODELAY + if (!(soap->omode & SOAP_IO_UDP) && setsockopt((SOAP_SOCKET)fd, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } +#endif +#endif + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Opening socket %d to host='%s' port=%d\n", fd, host, port)); +#ifndef WITH_IPV6 + soap->peerlen = sizeof(soap->peer); + memset((void*)&soap->peer, 0, sizeof(soap->peer)); + soap->peer.sin_family = AF_INET; + soap->errmode = 2; + if (soap->proxy_host) + { if (soap->fresolve(soap, soap->proxy_host, &soap->peer.sin_addr)) + { soap_set_sender_error(soap, tcp_error(soap), "get proxy host by name failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } + soap->peer.sin_port = htons((short)soap->proxy_port); + } + else + { if (soap->fresolve(soap, host, &soap->peer.sin_addr)) + { soap_set_sender_error(soap, tcp_error(soap), "get host by name failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } + soap->peer.sin_port = htons((short)port); + } + soap->errmode = 0; + if ((soap->omode & SOAP_IO_UDP)) + { +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return fd; + } +#endif +#ifndef WITH_LEAN + if (soap->connect_timeout) +#if defined(WIN32) + { u_long nonblocking = 1; + ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &nonblocking); + } +#elif defined(VXWORKS) + { u_long nonblocking = 1; + ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&nonblocking)); /* modified to use fd */ + } +#else + fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)|O_NONBLOCK); +#endif + else +#if defined(WIN32) + { u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &blocking); + } +#elif defined(VXWORKS) + { u_long blocking = 0; + ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&blocking)); + } +#else + fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)&~O_NONBLOCK); +#endif +#endif + for (;;) + { +#ifdef WITH_IPV6 + if (connect((SOAP_SOCKET)fd, res->ai_addr, res->ai_addrlen)) +#else + if (connect((SOAP_SOCKET)fd, (struct sockaddr*)&soap->peer, sizeof(soap->peer))) +#endif + { err = soap_socket_errno(fd); +#ifndef WITH_LEAN + if (err == SOAP_EADDRINUSE) + { soap->fclosesocket(soap, (SOAP_SOCKET)fd); + if (retry-- > 0) + goto again; + } + else if (soap->connect_timeout && (err == SOAP_EINPROGRESS || err == SOAP_EWOULDBLOCK)) + { struct timeval timeout; + SOAP_SOCKLEN_T k; + fd_set fds; + if (soap->connect_timeout > 0) + { timeout.tv_sec = soap->connect_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->connect_timeout/1000000; + timeout.tv_usec = -soap->connect_timeout%1000000; + } +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + { soap->error = SOAP_FD_EXCEEDED; +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; /* Hint: MUST increase FD_SETSIZE */ + } +#endif + FD_ZERO(&fds); + FD_SET((SOAP_SOCKET)fd, &fds); + for (;;) + { register int r = select((SOAP_SOCKET)(fd + 1), NULL, &fds, NULL, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n")); + soap_set_sender_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } + r = soap_socket_errno(fd); + if (r != SOAP_EINTR) + { soap->errnum = r; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); + soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } + } + k = (SOAP_SOCKLEN_T)sizeof(soap->errnum); + if (!getsockopt((SOAP_SOCKET)fd, SOL_SOCKET, SO_ERROR, (char*)&soap->errnum, &k) && !soap->errnum) /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */ + break; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); + if (!soap->errnum) + soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } +#endif +#ifdef WITH_IPV6 + if (res->ai_next) + { res = res->ai_next; + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + goto again; + } +#endif + if (err && err != SOAP_EINTR) + { soap->errnum = err; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); + soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } + } + else + break; + } +#ifdef WITH_IPV6 + soap->peerlen = 0; /* IPv6: already connected so use send() */ + freeaddrinfo(ressave); +#endif +#ifndef WITH_LEAN + if (soap->connect_timeout) +#if defined(WIN32) + { u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &blocking); + } +#elif defined(VXWORKS) + { u_long blocking = 0; + ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&blocking)); + } +#else + fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)&~O_NONBLOCK); +#endif +#endif + soap->socket = fd; + soap->imode &= ~SOAP_ENC_SSL; + soap->omode &= ~SOAP_ENC_SSL; + if (!soap_tag_cmp(endpoint, "https:*")) + { +#ifdef WITH_OPENSSL + BIO *bio; + int r; + if (soap->proxy_host) + { unsigned int k = soap->omode; /* make sure we only parse HTTP */ + size_t n = soap->count; /* save the content length */ + char *userid, *passwd; + char endp[sizeof(soap->endpoint)]; + soap->omode &= ~SOAP_ENC; /* mask IO and ENC */ + soap->omode |= SOAP_IO_BUFFER; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connecting to %s proxy server\n", soap->proxy_http_version)); + sprintf(soap->tmpbuf, "CONNECT %s:%d HTTP/%s", host, port, soap->proxy_http_version); + if (soap_begin_send(soap) + || (soap->error = soap->fposthdr(soap, soap->tmpbuf, NULL))) + { soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } +#ifndef WITH_LEAN + if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761) + { sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd); + strcpy(soap->tmpbuf, "Basic "); + soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, strlen(soap->tmpbuf + 262)); + if ((soap->error = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf))) + { soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return soap->error; + } + } +#endif + if ((soap->error = soap->fposthdr(soap, NULL, NULL)) + || soap_flush(soap)) + { soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + soap->omode = k; + k = soap->imode; + soap->imode &= ~SOAP_ENC; /* mask IO and ENC */ + strcpy(endp, soap->endpoint); + userid = soap->userid; /* preserve */ + passwd = soap->passwd; /* preserve */ + if ((soap->error = soap->fparse(soap))) + { soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + strcpy(soap->endpoint, endp); /* restore */ + soap->userid = userid; /* restore */ + soap->passwd = passwd; /* restore */ + soap->imode = k; /* restore */ + soap->count = n; /* restore */ + if (soap_begin_send(soap)) + { soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + } + if (!soap->ctx && (soap->error = soap->fsslauth(soap))) + { soap_set_sender_error(soap, "SSL error", "SSL authentication failed in tcp_connect(): check password, key file, and ca file.", SOAP_SSL_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + soap->ssl = SSL_new(soap->ctx); + if (!soap->ssl) + { soap->fclosesocket(soap, (SOAP_SOCKET)fd); + soap->error = SOAP_SSL_ERROR; + return SOAP_INVALID_SOCKET; + } + if (soap->session) + { if (!strcmp(soap->session_host, host) && soap->session_port == port) + SSL_set_session(soap->ssl, soap->session); + SSL_SESSION_free(soap->session); + soap->session = NULL; + } + soap->imode |= SOAP_ENC_SSL; + soap->omode |= SOAP_ENC_SSL; + bio = BIO_new_socket((SOAP_SOCKET)fd, BIO_NOCLOSE); + SSL_set_bio(soap->ssl, bio, bio); + /* Connect timeout: set SSL sockets to non-blocking */ +#ifndef WITH_LEAN + if (soap->connect_timeout) +#if defined(WIN32) + { u_long nonblocking = 1; + ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &nonblocking); + } +#elif defined(VXWORKS) + { u_long nonblocking = 1; + ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&nonblocking)); + } +#else + fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)|O_NONBLOCK); +#endif +#endif + /* Try connecting until success or timeout */ + for (;;) + { if ((r = SSL_connect(soap->ssl)) <= 0) + { int err = SSL_get_error(soap->ssl, r); + if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) + { soap_set_sender_error(soap, soap_ssl_error(soap, r), "SSL connect failed in tcp_connect()", SOAP_SSL_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + if (soap->connect_timeout) + { struct timeval timeout; + fd_set fds; + if (soap->connect_timeout > 0) + { timeout.tv_sec = soap->connect_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->connect_timeout/1000000; + timeout.tv_usec = -soap->connect_timeout%1000000; + } +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + { soap->error = SOAP_FD_EXCEEDED; + return SOAP_INVALID_SOCKET; /* Hint: MUST increase FD_SETSIZE */ + } +#endif + FD_ZERO(&fds); + FD_SET((SOAP_SOCKET)fd, &fds); + for (;;) + { int r = select((SOAP_SOCKET)(fd + 1), &fds, NULL, &fds, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n")); + soap_set_sender_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + } + continue; + } + } + break; + } + /* Set SSL sockets to non-blocking */ +#ifndef WITH_LEAN +#if defined(WIN32) + { u_long nonblocking = 1; + ioctlsocket((SOAP_SOCKET)fd, FIONBIO, &nonblocking); + } +#elif defined(VXWORKS) + { u_long nonblocking = 1; + ioctl((SOAP_SOCKET)fd, FIONBIO, (int)(&nonblocking)); + } +#else + fcntl((SOAP_SOCKET)fd, F_SETFL, fcntl((SOAP_SOCKET)fd, F_GETFL)|O_NONBLOCK); +#endif +#endif + /* Check server credentials when required */ + if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION)) + { int err; + if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK) + { soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL certificate presented by peer cannot be verified in tcp_connect()", SOAP_SSL_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + if (!(soap->ssl_flags & SOAP_SSL_SKIP_HOST_CHECK)) + { X509_NAME *subj; + int ext_count; + int ok = 0; + X509 *peer; + peer = SSL_get_peer_certificate(soap->ssl); + if (!peer) + { soap_set_sender_error(soap, "SSL error", "No SSL certificate was presented by the peer in tcp_connect()", SOAP_SSL_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + ext_count = X509_get_ext_count(peer); + if (ext_count > 0) + { int i; + for (i = 0; i < ext_count; i++) + { X509_EXTENSION *ext = X509_get_ext(peer, i); + const char *ext_str = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext))); + if (ext_str && !strcmp(ext_str, "subjectAltName")) + { X509V3_EXT_METHOD *meth = X509V3_EXT_get(ext); + void *ext_data; + unsigned char *data; + STACK_OF(CONF_VALUE) *val; + int j; + if (!meth) + break; + data = ext->value->data; +#if (OPENSSL_VERSION_NUMBER > 0x00907000L) + if (meth->it) + ext_data = ASN1_item_d2i(NULL, &data, ext->value->length, ASN1_ITEM_ptr(meth->it)); + else + { /* OpenSSL not perfectly portable at this point (?): + Some compilers appear to prefer + meth->d2i(NULL, (const unsigned char**)&data, ... + or + meth->d2i(NULL, &data, ext->value->length); + */ + ext_data = meth->d2i(NULL, &data, ext->value->length); + } +#else + ext_data = meth->d2i(NULL, &data, ext->value->length); +#endif + val = meth->i2v(meth, ext_data, NULL); + for (j = 0; j < sk_CONF_VALUE_num(val); j++) + { CONF_VALUE *nval = sk_CONF_VALUE_value(val, j); + if (nval && !strcmp(nval->name, "DNS") && !strcmp(nval->value, host)) + { ok = 1; + break; + } + } + } + if (ok) + break; + } + } + if (!ok && (subj = X509_get_subject_name(peer))) + { int i = -1; + do + { ASN1_STRING *name; + i = X509_NAME_get_index_by_NID(subj, NID_commonName, i); + if (i == -1) + break; + name = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subj, i)); + if (name && !soap_tag_cmp(host, (const char*)name)) + ok = 1; + else + { unsigned char *tmp = NULL; + ASN1_STRING_to_UTF8(&tmp, name); + if (tmp) + { if (!soap_tag_cmp(host, (const char*)tmp)) + ok = 1; + OPENSSL_free(tmp); + } + } + } while (!ok); + } + X509_free(peer); + if (!ok) + { soap_set_sender_error(soap, "SSL error", "SSL certificate host name mismatch in tcp_connect()", SOAP_SSL_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + return SOAP_INVALID_SOCKET; + } + } + } +#else + soap->fclosesocket(soap, (SOAP_SOCKET)fd); + soap->error = SOAP_SSL_ERROR; + return SOAP_INVALID_SOCKET; +#endif + } + return fd; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_bind(struct soap *soap, const char *host, int port, int backlog) +{ +#ifdef WITH_IPV6 + struct addrinfo *addrinfo = NULL; + struct addrinfo hints; + struct addrinfo res; + int err; +#endif +#ifndef WITH_LEAN + int len = SOAP_BUFLEN; + int set = 1; +#endif + if (soap_valid_socket(soap->master)) + { soap->fclosesocket(soap, (SOAP_SOCKET)soap->master); + soap->master = SOAP_INVALID_SOCKET; + } + soap->socket = SOAP_INVALID_SOCKET; + soap->errmode = 1; + if (tcp_init(soap)) + { soap_set_receiver_error(soap, tcp_error(soap), "TCP init failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#ifdef WITH_IPV6 + memset((void*)&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + hints.ai_socktype = SOCK_DGRAM; + else +#endif + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + soap->errmode = 2; + err = getaddrinfo(host, soap_int2s(soap, port), &hints, &addrinfo); + if (addrinfo) + { res = *addrinfo; + soap->peer = *((struct sockaddr_storage*)addrinfo->ai_addr); + soap->peerlen = addrinfo->ai_addrlen; + res.ai_addr = (struct sockaddr*)&soap->peer; + res.ai_addrlen = soap->peerlen; + freeaddrinfo(addrinfo); + } + if (err) + { soap_set_receiver_error(soap, gai_strerror(err), "getaddrinfo failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + soap->master = socket(res.ai_family, res.ai_socktype, res.ai_protocol); +#else +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + soap->master = (int)socket(AF_INET, SOCK_DGRAM, 0); + else +#endif + soap->master = (int)socket(AF_INET, SOCK_STREAM, 0); +#endif + soap->errmode = 0; + if (!soap_valid_socket(soap->master)) + { soap->errnum = soap_socket_errno(soap->master); + soap_set_receiver_error(soap, tcp_error(soap), "socket failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + soap->socket = soap->master; +#endif +#ifdef SOCKET_CLOSE_ON_EXEC +#ifdef WIN32 +#ifndef UNDER_CE + SetHandleInformation((HANDLE)soap->master, HANDLE_FLAG_INHERIT, 0); +#endif +#else + fcntl(soap->master, F_SETFD, 1); +#endif +#endif +#ifndef WITH_LEAN + if (soap->bind_flags && setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, soap->bind_flags, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->master); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->master); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + if (setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->master); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + if (setsockopt((SOAP_SOCKET)soap->master, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->master); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#ifdef TCP_NODELAY + if (!(soap->omode & SOAP_IO_UDP) && setsockopt((SOAP_SOCKET)soap->master, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->master); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#endif +#endif +#ifdef WITH_IPV6 + soap->errmode = 0; + if (bind((SOAP_SOCKET)soap->master, res.ai_addr, res.ai_addrlen)) + { soap->errnum = soap_socket_errno(soap->master); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n")); + soap_closesock(soap); + soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#else + soap->peerlen = sizeof(soap->peer); + memset((void*)&soap->peer, 0, sizeof(soap->peer)); + soap->peer.sin_family = AF_INET; + soap->errmode = 2; + if (host) + { if (soap->fresolve(soap, host, &soap->peer.sin_addr)) + { soap_set_receiver_error(soap, tcp_error(soap), "get host by name failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + } + else + soap->peer.sin_addr.s_addr = htonl(INADDR_ANY); + soap->peer.sin_port = htons((short)port); + soap->errmode = 0; + if (bind((SOAP_SOCKET)soap->master, (struct sockaddr*)&soap->peer, soap->peerlen)) + { soap->errnum = soap_socket_errno(soap->master); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n")); + soap_closesock(soap); + soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#endif + if (!(soap->omode & SOAP_IO_UDP) && listen((SOAP_SOCKET)soap->master, backlog)) + { soap->errnum = soap_socket_errno(soap->master); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n")); + soap_closesock(soap); + soap_set_receiver_error(soap, tcp_error(soap), "listen failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + return soap->master; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_poll(struct soap *soap) +{ +#ifndef WITH_LEAN + struct timeval timeout; + fd_set rfd, sfd, xfd; + int r; + timeout.tv_sec = 0; + timeout.tv_usec = 0; +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + return SOAP_FD_EXCEEDED; /* Hint: MUST increase FD_SETSIZE */ +#endif + FD_ZERO(&rfd); + FD_ZERO(&sfd); + FD_ZERO(&xfd); + if (soap_valid_socket(soap->socket)) + { FD_SET((SOAP_SOCKET)soap->socket, &rfd); + FD_SET((SOAP_SOCKET)soap->socket, &sfd); + FD_SET((SOAP_SOCKET)soap->socket, &xfd); + r = select((SOAP_SOCKET)(soap->socket + 1), &rfd, &sfd, &xfd, &timeout); + if (r > 0 && FD_ISSET((SOAP_SOCKET)soap->socket, &xfd)) + r = -1; + } + else if (soap_valid_socket(soap->master)) + { FD_SET((SOAP_SOCKET)soap->master, &sfd); + r = select((SOAP_SOCKET)(soap->master + 1), NULL, &sfd, NULL, &timeout); + } + else + return SOAP_OK; + if (r > 0) + { +#ifdef WITH_OPENSSL + if (soap->imode & SOAP_ENC_SSL) + { + if (soap_valid_socket(soap->socket) + && FD_ISSET((SOAP_SOCKET)soap->socket, &sfd) + && (!FD_ISSET((SOAP_SOCKET)soap->socket, &rfd) + || SSL_peek(soap->ssl, soap->tmpbuf, 1) > 0)) + return SOAP_OK; + } + else +#endif + if (soap_valid_socket(soap->socket) + && FD_ISSET((SOAP_SOCKET)soap->socket, &sfd) + && (!FD_ISSET((SOAP_SOCKET)soap->socket, &rfd) + || recv((SOAP_SOCKET)soap->socket, soap->tmpbuf, 1, MSG_PEEK) > 0)) + return SOAP_OK; + } + else if (r < 0) + { soap->errnum = soap_socket_errno(soap->master); + if ((soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) && soap_socket_errno(soap->master) != SOAP_EINTR) + { soap_set_receiver_error(soap, tcp_error(soap), "select failed in soap_poll()", SOAP_TCP_ERROR); + return soap->error = SOAP_TCP_ERROR; + } + } + else + soap->errnum = 0; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Polling: other end down on socket=%d select=%d\n", soap->socket, r)); + return SOAP_EOF; +#else + return SOAP_OK; +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_accept(struct soap *soap, int s, struct sockaddr *a, int *n) +{ int fd; + fd = (int)accept((SOAP_SOCKET)s, a, (SOAP_SOCKLEN_T*)n); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */ +#ifdef SOCKET_CLOSE_ON_EXEC +#ifdef WIN32 +#ifndef UNDER_CE + SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0); +#endif +#else + fcntl(fd, F_SETFD, FD_CLOEXEC); +#endif +#endif + return fd; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_accept(struct soap *soap) +{ int n = (int)sizeof(soap->peer); +#ifndef WITH_LEAN + int len = SOAP_BUFLEN; + int set = 1; +#endif + soap->error = SOAP_OK; +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + return soap->socket = soap->master; +#endif + memset((void*)&soap->peer, 0, sizeof(soap->peer)); + soap->socket = SOAP_INVALID_SOCKET; + soap->errmode = 0; + soap->keep_alive = 0; + if (soap_valid_socket(soap->master)) + { register int err; + for (;;) + { +#ifndef WITH_LEAN + if (soap->accept_timeout) + { struct timeval timeout; + fd_set fd; + if (soap->accept_timeout > 0) + { timeout.tv_sec = soap->accept_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->accept_timeout/1000000; + timeout.tv_usec = -soap->accept_timeout%1000000; + } +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + { soap->error = SOAP_FD_EXCEEDED; + return SOAP_INVALID_SOCKET; /* Hint: MUST increase FD_SETSIZE */ + } +#endif + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->master, &fd); + for (;;) + { register int r = select((SOAP_SOCKET)(soap->master + 1), &fd, &fd, &fd, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + soap_set_receiver_error(soap, "Timeout", "accept failed in soap_accept()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + r = soap_socket_errno(soap->master); + if (r != SOAP_EINTR) + { soap->errnum = r; + soap_closesock(soap); + soap_set_sender_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + } +#if defined(WIN32) + { u_long nonblocking = 1; + ioctlsocket((SOAP_SOCKET)soap->master, FIONBIO, &nonblocking); + } +#elif defined(VXWORKS) + { u_long nonblocking = 1; + ioctl((SOAP_SOCKET)soap->master, FIONBIO, (int)(&nonblocking)); + } +#else + fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL)|O_NONBLOCK); +#endif + } + else +#if defined(WIN32) + { u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)soap->master, FIONBIO, &blocking); + } +#elif defined(VXWORKS) + { u_long blocking = 0; + ioctl((SOAP_SOCKET)soap->master, FIONBIO, (int)(&blocking)); + } +#else + fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL)&~O_NONBLOCK); +#endif +#endif + soap->socket = soap->faccept(soap, soap->master, (struct sockaddr*)&soap->peer, &n); + soap->peerlen = (size_t)n; + if (soap_valid_socket(soap->socket)) + { +#ifdef WITH_IPV6 +/* Use soap->host to store the numeric form of the remote host */ + getnameinfo((struct sockaddr*)&soap->peer, n, soap->host, sizeof(soap->host), NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket %d from %s\n", soap->socket, soap->host)); + soap->ip = 0; /* info stored in soap->peer and soap->host */ + soap->port = 0; /* info stored in soap->peer and soap->host */ +#else + soap->ip = ntohl(soap->peer.sin_addr.s_addr); + soap->port = (int)ntohs(soap->peer.sin_port); /* does not return port number on some systems */ + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket %d at port %d from IP %d.%d.%d.%d\n", soap->socket, soap->port, (int)(soap->ip>>24)&0xFF, (int)(soap->ip>>16)&0xFF, (int)(soap->ip>>8)&0xFF, (int)soap->ip&0xFF)); +#endif +#ifndef WITH_LEAN + if (soap->accept_flags == SO_LINGER) + { struct linger linger; + memset((void*)&linger, 0, sizeof(linger)); + linger.l_onoff = 1; + linger.l_linger = 0; + if (setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger))) + { soap->errnum = soap_socket_errno(soap->socket); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } + } + else if (soap->accept_flags && setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, soap->accept_flags, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->socket); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } + if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->socket); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } + if (setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->socket); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } + if (setsockopt((SOAP_SOCKET)soap->socket, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->socket); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } +#ifdef TCP_NODELAY + if (!(soap->omode & SOAP_IO_UDP) && setsockopt((SOAP_SOCKET)soap->socket, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->socket); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } +#endif +#endif + if (soap->accept_timeout) + { +#if defined(WIN32) + u_long blocking = 0; + ioctlsocket((SOAP_SOCKET)soap->master, FIONBIO, &blocking); + ioctlsocket((SOAP_SOCKET)soap->socket, FIONBIO, &blocking); +#elif defined(VXWORKS) + u_long blocking = 0; + ioctl((SOAP_SOCKET)soap->master, FIONBIO, (int)(&blocking)); + ioctl((SOAP_SOCKET)soap->socket, FIONBIO, (int)(&blocking)); +#elif defined(PALM) + fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL,0)&~O_NONBLOCK); + fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL,0)&~O_NONBLOCK); +#elif defined(SYMBIAN) + long blocking = 0; + ioctl((SOAP_SOCKET)soap->master, 0/*FIONBIO*/, &blocking); +#else + fcntl((SOAP_SOCKET)soap->master, F_SETFL, fcntl((SOAP_SOCKET)soap->master, F_GETFL)&~O_NONBLOCK); + fcntl((SOAP_SOCKET)soap->socket, F_SETFL, fcntl((SOAP_SOCKET)soap->socket, F_GETFL)&~O_NONBLOCK); +#endif + } + soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0); + return soap->socket; + } + err = soap_socket_errno(soap->socket); + if (err != 0 && err != SOAP_EINTR && err != SOAP_EAGAIN) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept failed from %s\n", soap->host)); + soap->errnum = err; + soap_set_receiver_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } + } + } + else + { soap->errnum = 0; + soap_set_receiver_error(soap, tcp_error(soap), "no master socket in soap_accept()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_disconnect(struct soap *soap) +{ +#ifdef WITH_OPENSSL + if (soap->ssl) + { int r, s = 0; + if (soap->session) + { SSL_SESSION_free(soap->session); + soap->session = NULL; + } + if (*soap->host) + { soap->session = SSL_get1_session(soap->ssl); + if (soap->session) + { strcpy(soap->session_host, soap->host); + soap->session_port = soap->port; + } + } + r = SSL_shutdown(soap->ssl); + if (r == 0) + { if (soap_valid_socket(soap->socket)) + { struct timeval timeout; + fd_set fd; + if (soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 1)) + { /* + wait up to 10 seconds for close_notify to be sent by peer (if peer not + present, this avoids calling SSL_shutdown() which has a lengthy return + timeout) + */ +#ifndef WIN32 + if ((int)soap->socket < (int)FD_SETSIZE) + { +#endif + timeout.tv_sec = 10; + timeout.tv_usec = 0; + FD_ZERO(&fd); + FD_SET((SOAP_SOCKET)soap->socket, &fd); + r = select((SOAP_SOCKET)(soap->socket + 1), &fd, NULL, &fd, &timeout); + if (r <= 0 && soap_socket_errno(soap->socket) != SOAP_EINTR) + { soap->errnum = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connection lost...\n")); + soap->fclosesocket(soap, (SOAP_SOCKET)soap->socket); + soap->socket = SOAP_INVALID_SOCKET; + SSL_free(soap->ssl); + soap->ssl = NULL; + ERR_remove_state(0); + return SOAP_OK; + } +#ifndef WIN32 + } +#endif + } + } + r = SSL_shutdown(soap->ssl); + } + if (r != 1) + { s = ERR_get_error(); + if (s) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown failed: %d\n", SSL_get_error(soap->ssl, r))); + if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP)) + { soap->fclosesocket(soap, (SOAP_SOCKET)soap->socket); + soap->socket = SOAP_INVALID_SOCKET; + } + SSL_free(soap->ssl); + soap->ssl = NULL; + ERR_remove_state(0); + return SOAP_SSL_ERROR; + } + } + SSL_free(soap->ssl); + soap->ssl = NULL; + ERR_remove_state(0); + } +#endif + if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP)) + { soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 2); + soap->fclosesocket(soap, (SOAP_SOCKET)soap->socket); + soap->socket = SOAP_INVALID_SOCKET; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_closesocket(struct soap *soap, SOAP_SOCKET fd) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Close socket %d\n", (int)fd)); + return soap_closesocket(fd); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_shutdownsocket(struct soap *soap, SOAP_SOCKET fd, int how) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown socket %d how=%d\n", (int)fd, how)); + return shutdown(fd, how); +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_closesock(struct soap *soap) +{ register int status = soap->error; + if (status == SOAP_EOF || status == SOAP_TCP_ERROR || status == SOAP_SSL_ERROR || !soap->keep_alive) + { if (soap->fclose && (soap->error = soap->fclose(soap))) + return soap->error; + soap->keep_alive = 0; + } +#ifdef WITH_ZLIB + if (soap->zlib_state == SOAP_ZLIB_DEFLATE) + deflateEnd(&soap->d_stream); + else if (soap->zlib_state == SOAP_ZLIB_INFLATE) + inflateEnd(&soap->d_stream); + soap->zlib_state = SOAP_ZLIB_NONE; +#endif + return soap->error = status; +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_hash(register const char *s) +{ register size_t h = 0; + while (*s) + h = 65599*h + *s++; + return h % SOAP_IDHASH; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static void +soap_init_pht(struct soap *soap) +{ register int i; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing pointer hashtable\n")); + soap->pblk = NULL; + soap->pidx = 0; + for (i = 0; i < (int)SOAP_PTRHASH; i++) + soap->pht[i] = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_new1(soap_mode mode) +{ return soap_new2(mode, mode); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_new() +{ return soap_new2(SOAP_IO_DEFAULT, SOAP_IO_DEFAULT); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_new2(soap_mode imode, soap_mode omode) +{ struct soap *soap = (struct soap*)malloc(sizeof(struct soap)); + if (soap) + soap_init2(soap, imode, omode); + return soap; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_free(struct soap *soap) +{ soap_done(soap); + free(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_del(struct soap *soap) +{ free(soap); +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static void +soap_free_pht(struct soap *soap) +{ register struct soap_pblk *pb, *next; + register int i; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free pointer hashtable\n")); + for (pb = soap->pblk; pb; pb = next) + { next = pb->next; + SOAP_FREE(soap, pb); + } + soap->pblk = NULL; + soap->pidx = 0; + for (i = 0; i < (int)SOAP_PTRHASH; i++) + soap->pht[i] = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_embed(struct soap *soap, const void *p, const struct soap_array *a, int n, const char *tag, int type) +{ register int i; + struct soap_plist *pp; + if (soap->version != 1) + soap->encoding = 1; + if (a) + i = soap_array_pointer_lookup(soap, p, a, n, type, &pp); + else + i = soap_pointer_lookup(soap, p, type, &pp); + if (i) + { if (soap_is_embedded(soap, pp) + || soap_is_single(soap, pp)) + return 0; + soap_set_embedded(soap, pp); + } + return i; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_pointer_lookup(struct soap *soap, const void *p, int type, struct soap_plist **ppp) +{ register struct soap_plist *pp; + *ppp = NULL; + if (p) + { for (pp = soap->pht[soap_hash_ptr(p)]; pp; pp = pp->next) + { if (pp->ptr == p && pp->type == type) + { *ppp = pp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d id=%d\n", p, type, pp->id)); + return pp->id; + } + } + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d: not found\n", p, type)); + return 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_pointer_enter(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp) +{ register size_t h; + register struct soap_plist *pp; + if (!soap->pblk || soap->pidx >= SOAP_PTRBLK) + { register struct soap_pblk *pb = (struct soap_pblk*)SOAP_MALLOC(soap, sizeof(struct soap_pblk)); + if (!pb) + { soap->error = SOAP_EOM; + return 0; + } + pb->next = soap->pblk; + soap->pblk = pb; + soap->pidx = 0; + } + *ppp = pp = &soap->pblk->plist[soap->pidx++]; + if (a) + h = soap_hash_ptr(a->__ptr); + else + h = soap_hash_ptr(p); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pointer enter location=%p array=%p size=%d dim=%d type=%d id=%d\n", p, a?a->__ptr:NULL, a?a->__size:0, n, type, soap->idnum+1)); + pp->next = soap->pht[h]; + pp->type = type; + pp->mark1 = 0; + pp->mark2 = 0; + pp->ptr = p; + pp->array = a; + soap->pht[h] = pp; + pp->id = ++soap->idnum; + return pp->id; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_array_pointer_lookup(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp) +{ register struct soap_plist *pp; + *ppp = NULL; + if (!p || !a->__ptr) + return 0; + for (pp = soap->pht[soap_hash_ptr(a->__ptr)]; pp; pp = pp->next) + { if (pp->type == type && pp->array && pp->array->__ptr == a->__ptr) + { register int i; + for (i = 0; i < n; i++) + if (((const int*)&pp->array->__size)[i] != ((const int*)&a->__size)[i]) + break; + if (i == n) + { *ppp = pp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d id=%d\n", a->__ptr, type, pp->id)); + return pp->id; + } + } + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d: not found\n", a->__ptr, type)); + return 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_begin_count(struct soap *soap) +{ +#ifndef WITH_LEANER + if ((soap->mode & SOAP_ENC_DIME) || (soap->omode & SOAP_ENC_DIME)) + soap->mode = soap->omode | SOAP_IO_LENGTH | SOAP_ENC_DIME; + else +#endif + { soap->mode = soap->omode; + if ((soap->mode & SOAP_IO) == SOAP_IO_STORE + || (((soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_ENC_XML)) +#ifndef WITH_LEANER + && !soap->fpreparesend +#endif + )) + soap->mode &= ~SOAP_IO_LENGTH; + else + soap->mode |= SOAP_IO_LENGTH; + } +#ifdef WITH_ZLIB + if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH) + { if (!(soap->mode & SOAP_ENC_DIME)) + soap->mode &= ~SOAP_IO_LENGTH; + if (soap->mode & SOAP_ENC_XML) + soap->mode |= SOAP_IO_BUFFER; + else + soap->mode |= SOAP_IO_STORE; + } +#endif + if (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH)) + soap->mode |= SOAP_XML_TREE; +#ifndef WITH_LEANER + if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME)) + soap->mode |= SOAP_ENC_MIME; + else + soap->mode &= ~SOAP_ENC_MTOM; + if (soap->mode & SOAP_ENC_MIME) + soap_select_mime_boundary(soap); + soap->dime.list = soap->dime.last; /* keep track of last DIME attachment */ +#endif + soap->count = 0; + soap->ns = 0; + soap->null = 0; + soap->position = 0; + soap->mustUnderstand = 0; + soap->encoding = 0; + soap->part = SOAP_BEGIN; + soap->idnum = 0; + soap_clr_attr(soap); + soap_set_local_namespaces(soap); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin count phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count)); +#ifndef WITH_LEANER + soap->dime.count = 0; /* count # of attachments */ + soap->dime.size = 0; /* accumulate total size of attachments */ + if (soap->fprepareinit && (soap->mode & SOAP_IO) != SOAP_IO_STORE) + return soap->error = soap->fprepareinit(soap); +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_end_count(struct soap *soap) +{ +#ifndef WITH_LEANER + if (soap->fpreparefinal) + return soap->error = soap->fpreparefinal(soap); +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of count phase\n")); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_begin_send(struct soap *soap) +{ soap->error = SOAP_OK; + soap->mode = soap->omode | (soap->mode & (SOAP_IO_LENGTH | SOAP_ENC_DIME)); +#ifdef WITH_ZLIB + if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH) + { if (soap->mode & SOAP_ENC_XML) + soap->mode |= SOAP_IO_BUFFER; + else + soap->mode |= SOAP_IO_STORE; + } +#endif +#ifdef WITH_UDP + if ((soap->mode & SOAP_IO_UDP)) + { soap->mode |= SOAP_ENC_XML; + if (soap->count > SOAP_BUFLEN) + return soap->error = SOAP_UDP_ERROR; + } +#endif + if ((soap->mode & SOAP_IO) == SOAP_IO_FLUSH && soap_valid_socket(soap->socket)) + { if (soap->count || (soap->mode & SOAP_IO_LENGTH) || (soap->mode & SOAP_ENC_XML)) + soap->mode |= SOAP_IO_BUFFER; + else + soap->mode |= SOAP_IO_STORE; + } + soap->mode &= ~SOAP_IO_LENGTH; + if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) + soap_new_block(soap); + if (!(soap->mode & SOAP_IO_KEEPALIVE)) + soap->keep_alive = 0; + if (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH)) + soap->mode |= SOAP_XML_TREE; +#ifndef WITH_LEANER + if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME)) + { soap->mode |= SOAP_ENC_MIME; + soap->mode &= ~SOAP_ENC_DIME; + } + else + soap->mode &= ~SOAP_ENC_MTOM; + if (soap->mode & SOAP_ENC_MIME) + soap_select_mime_boundary(soap); +#ifdef WIN32 +#ifndef UNDER_CE +#ifndef WITH_FASTCGI + if (!soap_valid_socket(soap->socket)) /* Set win32 stdout or soap->sendfd to BINARY, e.g. to support DIME */ +#ifdef __BORLANDC__ + setmode((SOAP_SOCKET)soap->sendfd, O_BINARY); +#else + _setmode((SOAP_SOCKET)soap->sendfd, _O_BINARY); +#endif +#endif +#endif +#endif +#endif + if (soap->mode & SOAP_IO) + { soap->bufidx = 0; + soap->buflen = 0; + } + soap->chunksize = 0; + soap->ns = 0; + soap->null = 0; + soap->position = 0; + soap->mustUnderstand = 0; + soap->encoding = 0; + soap->idnum = 0; + soap->level = 0; + soap_clr_attr(soap); + soap_set_local_namespaces(soap); +#ifdef WITH_ZLIB + soap->z_ratio_out = 1.0; + if ((soap->mode & SOAP_ENC_ZLIB) && soap->zlib_state != SOAP_ZLIB_DEFLATE) + { +#ifdef WITH_GZIP + memcpy(soap->z_buf, "\37\213\10\0\0\0\0\0\0\377", 10); + soap->d_stream.next_out = (Byte*)soap->z_buf + 10; + soap->d_stream.avail_out = SOAP_BUFLEN - 10; + soap->z_crc = crc32(0L, NULL, 0); + if (deflateInit2(&soap->d_stream, soap->z_level, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY) != Z_OK) +#else + soap->d_stream.next_out = (Byte*)soap->z_buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + if (deflateInit(&soap->d_stream, soap->z_level) != Z_OK) +#endif + return soap->error = SOAP_ZLIB_ERROR; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflate initialized\n")); + soap->zlib_state = SOAP_ZLIB_DEFLATE; + } +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin send phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count)); + soap->part = SOAP_BEGIN; +#ifndef WITH_LEANER + if (soap->fprepareinit && (soap->mode & SOAP_IO) == SOAP_IO_STORE) + soap->fprepareinit(soap); +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_embedded(struct soap *soap, const void *p, int t) +{ struct soap_plist *pp; + if (soap_pointer_lookup(soap, p, t, &pp)) + { pp->mark1 = 1; + pp->mark2 = 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded %p type=%d mark set to 1\n", p, t)); + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_reference(struct soap *soap, const void *p, int t) +{ struct soap_plist *pp; + if (!p || (soap->mode & SOAP_XML_TREE)) + return 1; + if (soap_pointer_lookup(soap, p, t, &pp)) + { if (pp->mark1 == 0) + { pp->mark1 = 2; + pp->mark2 = 2; + } + } + else if (soap_pointer_enter(soap, p, NULL, 0, t, &pp)) + { pp->mark1 = 0; + pp->mark2 = 0; + } + else + return 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reference %p type=%d (%d %d)\n", p, t, (int)pp->mark1, (int)pp->mark2)); + return pp->mark1; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_array_reference(struct soap *soap, const void *p, const struct soap_array *a, int n, int t) +{ register int i; + struct soap_plist *pp; + if (!p || !a->__ptr) + return 1; + i = soap_array_pointer_lookup(soap, p, a, n, t, &pp); + if (i) + { if (pp->mark1 == 0) + { pp->mark1 = 2; + pp->mark2 = 2; + } + } + else if (!soap_pointer_enter(soap, p, a, n, t, &pp)) + return 1; + else + { pp->mark1 = 0; + pp->mark2 = 0; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array reference %p ptr=%p dim=%d type=%d (%d %d)\n", p, a->__ptr, n, t, (int)pp->mark1, (int)pp->mark2)); + return pp->mark1; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_embedded_id(struct soap *soap, int id, const void *p, int t) +{ struct soap_plist *pp = NULL; + if (soap->mode & SOAP_XML_TREE) + return id; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id %p type=%d id=%d\n", p, t, id)); + if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER) + { if (id < 0) + { id = soap_pointer_lookup(soap, p, t, &pp); + if (id) + { if (soap->mode & SOAP_IO_LENGTH) + pp->mark1 = 2; + else + pp->mark2 = 2; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id multiref id=%d %p type=%d = (%d %d)\n", id, p, t, (int)pp->mark1, (int)pp->mark2)); + } + return -1; + } + return id; + } + if (id < 0) + id = soap_pointer_lookup(soap, p, t, &pp); + else if (id && !soap_pointer_lookup(soap, p, t, &pp)) + return 0; + if (id && pp) + { if (soap->mode & SOAP_IO_LENGTH) + pp->mark1 = 1; + else + pp->mark2 = 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id embedded ref id=%d %p type=%d = (%d %d)\n", id, p, t, (int)pp->mark1, (int)pp->mark2)); + } + return id; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_is_embedded(struct soap *soap, struct soap_plist *pp) +{ if (!pp) + return 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Is embedded? %d %d\n", (int)pp->mark1, (int)pp->mark2)); + if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER) + { if (soap->mode & SOAP_IO_LENGTH) + return pp->mark1 != 0; + return pp->mark2 != 0; + } + if (soap->mode & SOAP_IO_LENGTH) + return pp->mark1 == 1; + return pp->mark2 == 1; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_is_single(struct soap *soap, struct soap_plist *pp) +{ if (soap->part == SOAP_IN_HEADER) + return 1; + if (!pp) + return 0; + if (soap->mode & SOAP_IO_LENGTH) + return pp->mark1 == 0; + return pp->mark2 == 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_embedded(struct soap *soap, struct soap_plist *pp) +{ if (!pp) + return; + if (soap->mode & SOAP_IO_LENGTH) + pp->mark1 = 1; + else + pp->mark2 = 1; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_attachment(struct soap *soap, const char *tag, int id, const void *p, const struct soap_array *a, const char *aid, const char *atype, const char *aoptions, int n, const char *type, int t) +{ struct soap_plist *pp; + int i; + if (!p || !a->__ptr || (!aid && !atype)) + return soap_element_id(soap, tag, id, p, a, n, type, t); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attachment tag='%s' id='%s' (%d) type='%s'\n", tag, aid?aid:"", id, atype?atype:"")); + i = soap_array_pointer_lookup(soap, p, a, n, t, &pp); + if (!i) + { i = soap_pointer_enter(soap, p, a, n, t, &pp); + if (!i) + { soap->error = SOAP_EOM; + return -1; + } + } + if (id <= 0) + id = i; + if (!aid) + { sprintf(soap->tmpbuf, soap->dime_id_format, id); + aid = soap_strdup(soap, soap->tmpbuf); + } + /* Add MTOM xop:Include element when necessary */ + /* TODO: this code to be obsoleted with new import/xop.h conventions */ + if ((soap->mode & SOAP_ENC_MTOM) && strcmp(tag, "xop:Include")) + { if (soap_element_begin_out(soap, tag, 0, type) + || soap_element_href(soap, "xop:Include", 0, "href", aid) + || soap_element_end_out(soap, tag)) + return soap->error; + } + else if (soap_element_href(soap, tag, 0, "href", aid)) + return soap->error; + if (soap->mode & SOAP_IO_LENGTH) + { if (pp->mark1 != 3) + { struct soap_multipart *content; + if (soap->mode & SOAP_ENC_MTOM) + content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, (char*)a->__ptr, a->__size); + else + content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, (char*)a->__ptr, a->__size); + if (!content) + { soap->error = SOAP_EOM; + return -1; + } + if (!strncmp(aid, "cid:", 4)) /* RFC 2111 */ + { if (soap->mode & SOAP_ENC_MTOM) + { char *s = (char*)soap_malloc(soap, strlen(aid) - 1); + if (s) + { *s = '<'; + strcpy(s + 1, aid + 4); + strcat(s, ">"); + content->id = s; + } + } + else + content->id = aid + 4; + } + else + content->id = aid; + content->type = atype; + content->options = aoptions; + content->encoding = SOAP_MIME_BINARY; + pp->mark1 = 3; + } + } + else + pp->mark2 = 3; + return -1; +} +#endif +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static void +soap_init_iht(struct soap *soap) +{ register int i; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing ID hashtable\n")); + for (i = 0; i < SOAP_IDHASH; i++) + soap->iht[i] = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static void +soap_free_iht(struct soap *soap) +{ register int i; + register struct soap_ilist *ip, *p; + register struct soap_flist *fp, *fq; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free ID hashtable\n")); + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = p) + { for (fp = ip->flist; fp; fp = fq) + { fq = fp->next; + SOAP_FREE(soap, fp); + } + p = ip->next; + SOAP_FREE(soap, ip); + } + soap->iht[i] = NULL; + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +struct soap_ilist * +SOAP_FMAC2 +soap_lookup(struct soap *soap, const char *id) +{ register struct soap_ilist *ip; + for (ip = soap->iht[soap_hash(id)]; ip; ip = ip->next) + if (!strcmp(ip->id, id)) + return ip; + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +struct soap_ilist * +SOAP_FMAC2 +soap_enter(struct soap *soap, const char *id) +{ register size_t h; + register struct soap_ilist *ip; + ip = (struct soap_ilist*)SOAP_MALLOC(soap, sizeof(struct soap_ilist) + strlen(id)); + if (ip) + { h = soap_hash(id); + strcpy(ip->id, id); + ip->next = soap->iht[h]; + soap->iht[h] = ip; + return ip; + } + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_malloc(struct soap *soap, size_t n) +{ register char *p; + if (!n) + return (void*)SOAP_NON_NULL; + if (!soap) + return SOAP_MALLOC(soap, n); + if (soap->fmalloc) + p = (char*)soap->fmalloc(soap, n); + else + { n += sizeof(short); + n += (-(long)n) & (sizeof(void*)-1); /* align at 4-, 8- or 16-byte boundary */ + if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(void*) + sizeof(size_t)))) + { soap->error = SOAP_EOM; + return NULL; + } + /* set the canary to detect corruption */ + *(short*)(p + n - sizeof(short)) = (short)SOAP_CANARY; + /* keep chain of alloced cells for destruction */ + *(void**)(p + n) = soap->alist; + *(size_t*)(p + n + sizeof(void*)) = n; + soap->alist = p + n; + } + soap->alloced = 1; + return p; +} +#endif + +/******************************************************************************/ +#ifdef SOAP_MEM_DEBUG +static void +soap_init_mht(struct soap *soap) +{ register int i; + for (i = 0; i < (int)SOAP_PTRHASH; i++) + soap->mht[i] = NULL; +} +#endif + +/******************************************************************************/ +#ifdef SOAP_MEM_DEBUG +static void +soap_free_mht(struct soap *soap) +{ register int i; + register struct soap_mlist *mp, *mq; + for (i = 0; i < (int)SOAP_PTRHASH; i++) + { for (mp = soap->mht[i]; mp; mp = mq) + { mq = mp->next; + if (mp->live) + fprintf(stderr, "%s(%d): malloc() = %p not freed (memory leak or forgot to call soap_end()?)\n", mp->file, mp->line, mp->ptr); + free(mp); + } + soap->mht[i] = NULL; + } +} +#endif + +/******************************************************************************/ +#ifdef SOAP_MEM_DEBUG +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_track_malloc(struct soap *soap, const char *file, int line, size_t size) +{ register void *p = malloc(size); + if (soap) + { register size_t h = soap_hash_ptr(p); + register struct soap_mlist *mp = (struct soap_mlist*)malloc(sizeof(struct soap_mlist)); + if (soap->fdebug[SOAP_INDEX_TEST]) + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): malloc(%lu) = %p\n", file, line, (unsigned long)size, p)); + mp->next = soap->mht[h]; + mp->ptr = p; + mp->file = file; + mp->line = line; + mp->live = 1; + soap->mht[h] = mp; + } + return p; +} +#endif + +/******************************************************************************/ +#ifdef SOAP_MEM_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_track_free(struct soap *soap, const char *file, int line, void *p) +{ register size_t h = soap_hash_ptr(p); + register struct soap_mlist *mp; + for (mp = soap->mht[h]; mp; mp = mp->next) + if (mp->ptr == p) + break; + if (mp) + { if (mp->live) + { free(p); + if (soap->fdebug[SOAP_INDEX_TEST]) + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): free(%p)\n", file, line, p)); + mp->live = 0; + } + else + fprintf(stderr, "%s(%d): free(%p) double free of pointer malloced at %s(%d)\n", file, line, p, mp->file, mp->line); + } + else + fprintf(stderr, "%s(%d): free(%p) pointer not malloced\n", file, line, p); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_MEM_DEBUG +static void +soap_track_unlink(struct soap *soap, const void *p) +{ register size_t h = soap_hash_ptr(p); + register struct soap_mlist *mp; + for (mp = soap->mht[h]; mp; mp = mp->next) + if (mp->ptr == p) + break; + if (mp) + mp->live = 0; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_dealloc(struct soap *soap, void *p) +{ if (soap_check_state(soap)) + return; + if (p) + { register char **q; + for (q = (char**)&soap->alist; *q; q = *(char***)q) + { + if (*(short*)(char*)(*q - sizeof(short)) != (short)SOAP_CANARY) + { fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n"); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n")); + DBGHEX(TEST, *q - 200, 200); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n")); + soap->error = SOAP_MOE; + return; + } + if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*)))) + { *q = **(char***)q; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Freed data at %p\n", p)); + SOAP_FREE(soap, p); + return; + } + } + soap_delete(soap, p); + } + else + { register char *q; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free all soap_malloc() data\n")); + while (soap->alist) + { q = (char*)soap->alist; + if (*(short*)(char*)(q - sizeof(short)) != (short)SOAP_CANARY) + { fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n"); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n")); + DBGHEX(TEST, q - 200, 200); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n")); + soap->error = SOAP_MOE; + return; + } + soap->alist = *(void**)q; + q -= *(size_t*)(q + sizeof(void*)); + SOAP_FREE(soap, q); + } + } + /* we must assume these were deallocated: */ + soap->action = NULL; + soap->fault = NULL; + soap->header = NULL; + soap->userid = NULL; + soap->passwd = NULL; + soap->authrealm = NULL; +#ifndef WITH_LEANER + soap_clr_mime(soap); +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_delete(struct soap *soap, void *p) +{ register struct soap_clist **cp; + if (soap_check_state(soap)) + return; + cp = &soap->clist; + if (p) + { while (*cp) + { if (p == (*cp)->ptr) + { register struct soap_clist *q = *cp; + *cp = q->next; + if (q->fdelete(q)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: deletion callback failed for object type %d\n", q->ptr, q->type)); +#ifdef SOAP_MEM_DEBUG + fprintf(stderr, "new(object type = %d) = %p not freed: deletion callback failed\n", q->type, q->ptr); +#endif + } + SOAP_FREE(soap, q); + return; + } + cp = &(*cp)->next; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: address not in list\n", p)); + } + else + { while (*cp) + { register struct soap_clist *q = *cp; + *cp = q->next; + if (q->fdelete(q)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: deletion callback failed for object type %d\n", q->ptr, q->type)); +#ifdef SOAP_MEM_DEBUG + fprintf(stderr, "new(object type = %d) = %p not freed: deletion callback failed\n", q->type, q->ptr); +#endif + } + SOAP_FREE(soap, q); + } + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +struct soap_clist * +SOAP_FMAC2 +soap_link(struct soap *soap, void *p, int t, int n, int (*fdelete)(struct soap_clist*)) +{ register struct soap_clist *cp; + if ((cp = (struct soap_clist*)SOAP_MALLOC(soap, sizeof(struct soap_clist)))) + { cp->next = soap->clist; + cp->type = t; + cp->size = n; + cp->ptr = p; + cp->fdelete = fdelete; + soap->clist = cp; + } + return cp; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_unlink(struct soap *soap, const void *p) +{ register char **q; + register struct soap_clist **cp; + if (!soap || !p) + return; + for (q = (char**)&soap->alist; *q; q = *(char***)q) + { if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*)))) + { *q = **(char***)q; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked data %p\n", p)); +#ifdef SOAP_DEBUG + soap_track_unlink(soap, p); +#endif + return; + } + } + for (cp = &soap->clist; *cp; cp = &(*cp)->next) + { if (p == (*cp)->ptr) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked class instance %p\n", p)); + q = (char**)*cp; + *cp = (*cp)->next; + SOAP_FREE(soap, q); + return; + } + } +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_lookup_type(struct soap *soap, const char *id) +{ register struct soap_ilist *ip; + if (id && *id) + { ip = soap_lookup(soap, id); + if (ip) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup id='%s' type=%d\n", id, ip->type)); + return ip->type; + } + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "lookup type id='%s' NOT FOUND! Need to get it from xsi:type\n", id)); + return 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_id_lookup(struct soap *soap, const char *id, void **p, int t, size_t n, unsigned int k) +{ struct soap_ilist *ip; + void **q; + if (!p || !id || !*id) + return p; + ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */ + if (!ip) + { ip = soap_enter(soap, id); /* new hash table entry for string id */ + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding first href='%s' type=%d %p (%u bytes)\n", id, t, p, (unsigned int)n)); + ip->type = t; + ip->size = n; + ip->link = p; + ip->copy = NULL; + ip->flist = NULL; + ip->ptr = NULL; + ip->level = k; + *p = NULL; + } + else if (ip->ptr) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolved href='%s' type=%d location=%p (%u bytes)\n", id, t, ip->ptr, (unsigned int)n)); + if (ip->type != t) + { strcpy(soap->id, id); + soap->error = SOAP_HREF; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility: id type=%d href type=%d\n", ip->type, t)); + return NULL; + } + while (ip->level < k) + { q = (void**)soap_malloc(soap, sizeof(void*)); + if (!q) + return NULL; + *p = (void*)q; + p = q; + k--; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); + } + *p = ip->ptr; + } + else if (ip->level > k) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving level %u pointers to href='%s'\n", ip->level, id)); + while (ip->level > k) + { void *s, **r = &ip->link; + q = (void**)ip->link; + while (q) + { *r = (void*)soap_malloc(soap, sizeof(void*)); + s = *q; + *q = *r; + r = (void**)*r; + q = (void**)s; + } + *r = NULL; + ip->size = n; + ip->copy = NULL; + ip->level = ip->level - 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); + } + q = (void**)ip->link; + ip->link = p; + *p = (void*)q; + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarded href='%s' type=%d location=%p (%u bytes)\n", id, t, p, (unsigned int)n)); + while (ip->level < k) + { q = (void**)soap_malloc(soap, sizeof(void*)); + *p = q; + p = q; + k--; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); + } + q = (void**)ip->link; + ip->link = p; + *p = (void*)q; + } + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_id_forward(struct soap *soap, const char *href, void *p, size_t len, int st, int tt, size_t n, unsigned int k, void (*fcopy)(struct soap*, int, int, void*, size_t, const void*, size_t)) +{ struct soap_ilist *ip; + if (!p || !href || !*href) + return p; + ip = soap_lookup(soap, href); /* lookup pointer to hash table entry for string id */ + if (!ip) + { ip = soap_enter(soap, href); /* new hash table entry for string id */ + ip->type = st; + ip->size = n; + ip->link = NULL; + ip->copy = NULL; + ip->ptr = NULL; + ip->level = 0; + ip->flist = NULL; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "New entry href='%s' type=%d size=%lu level=%d location=%p\n", href, st, (unsigned long)n, k, p)); + } + else if (ip->type != st || (ip->level == k && ip->size != n)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n", href, ip->type, (unsigned long)ip->size, k, st, (unsigned long)n)); + strcpy(soap->id, href); + soap->error = SOAP_HREF; + return NULL; + } + if (fcopy || n < sizeof(void*) || *href != '#') + { register struct soap_flist *fp = (struct soap_flist*)SOAP_MALLOC(soap, sizeof(struct soap_flist)); + if (!fp) + { soap->error = SOAP_EOM; + return NULL; + } + fp->next = ip->flist; + fp->type = tt; + fp->ptr = p; + fp->level = k; + fp->len = len; + if (fcopy) + fp->fcopy = fcopy; + else + fp->fcopy = soap_fcopy; + ip->flist = fp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding type=%d (target type=%d) size=%lu location=%p level=%u len=%lu href='%s'\n", st, tt, (unsigned long)n, p, k, (unsigned long)len, href)); + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding copying address %p for type=%d href='%s'\n", p, st, href)); + *(void**)p = ip->copy; + ip->copy = p; + } + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_id_enter(struct soap *soap, const char *id, void *p, int t, size_t n, unsigned int k, const char *type, const char *arrayType, void *(*finstantiate)(struct soap*, int, const char*, const char*, size_t*)) +{ +#ifndef WITH_NOIDREF + struct soap_ilist *ip; +#endif + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Enter id='%s' type=%d loc=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k)); + soap->alloced = 0; + if (!p) + { if (finstantiate) + p = finstantiate(soap, t, type, arrayType, &n); + else + p = soap_malloc(soap, n); + if (p) + soap->alloced = 1; + } +#ifndef WITH_NOIDREF + if (!id || !*id) +#endif + return p; +#ifndef WITH_NOIDREF + ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */ + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Lookup entry id='%s for location=%p'\n", id, p)); + if (!ip) + { ip = soap_enter(soap, id); /* new hash table entry for string id */ + ip->type = t; + ip->link = NULL; + ip->copy = NULL; + ip->flist = NULL; + ip->size = n; + ip->ptr = p; + ip->level = k; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "New entry id='%s' type=%d size=%lu level=%u location=%p\n", id, t, (unsigned long)n, k, p)); + } + else if ((ip->type != t || (ip->level == k && ip->size != n)) && (ip->copy || ip->flist)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n", id, ip->type, (unsigned long)ip->size, k, t, (unsigned long)n)); + strcpy(soap->id, id); + soap->error = SOAP_HREF; + return NULL; + } + else if (ip->ptr) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Multiply defined id='%s'\n", id)); + strcpy(soap->id, id); + soap->error = SOAP_DUPLICATE_ID; + return NULL; + } + else + { ip->size = n; + ip->ptr = p; + ip->level = k; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update entry id='%s' type=%d location=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k)); + } + return ip->ptr; +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_fcopy(struct soap *soap, int st, int tt, void *p, size_t len, const void *q, size_t n) +{ DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Copying data type=%d (target type=%d) %p -> %p (%lu bytes)\n", st, tt, q, p, (unsigned long)n)); + memcpy(p, q, n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_end_send(struct soap *soap) +{ +#ifndef WITH_LEANER + if (soap->dime.list) + { /* SOAP body referenced attachments must appear first */ + soap->dime.last->next = soap->dime.first; + soap->dime.first = soap->dime.list->next; + soap->dime.list->next = NULL; + soap->dime.last = soap->dime.list; + } + if (soap_putdime(soap) || soap_putmime(soap)) + return soap->error; + soap->mime.list = NULL; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->dime.list = NULL; + soap->dime.first = NULL; + soap->dime.last = NULL; +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End send\n")); + if (soap->mode & SOAP_IO) /* need to flush the remaining data in buffer */ + { if (soap_flush(soap)) +#ifdef WITH_ZLIB + { if (soap->mode & SOAP_ENC_ZLIB && soap->zlib_state == SOAP_ZLIB_DEFLATE) + { soap->zlib_state = SOAP_ZLIB_NONE; + deflateEnd(&soap->d_stream); + } + return soap->error; + } +#else + return soap->error; +#endif +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { int r; + soap->d_stream.avail_in = 0; + do + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating remainder\n")); + r = deflate(&soap->d_stream, Z_FINISH); + if (soap->d_stream.avail_out != SOAP_BUFLEN) + { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN - soap->d_stream.avail_out)) + { soap->zlib_state = SOAP_ZLIB_NONE; + deflateEnd(&soap->d_stream); + return soap->error; + } + soap->d_stream.next_out = (Byte*)soap->z_buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + } + } while (r == Z_OK); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out)); + soap->z_ratio_out = (float)soap->d_stream.total_out / (float)soap->d_stream.total_in; + soap->mode &= ~SOAP_ENC_ZLIB; + soap->zlib_state = SOAP_ZLIB_NONE; + if (deflateEnd(&soap->d_stream) != Z_OK || r != Z_STREAM_END) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to end deflate: %s\n", soap->d_stream.msg?soap->d_stream.msg:"")); + return soap->error = SOAP_ZLIB_ERROR; + } +#ifdef WITH_GZIP + soap->z_buf[0] = soap->z_crc & 0xFF; + soap->z_buf[1] = (soap->z_crc >> 8) & 0xFF; + soap->z_buf[2] = (soap->z_crc >> 16) & 0xFF; + soap->z_buf[3] = (soap->z_crc >> 24) & 0xFF; + soap->z_buf[4] = soap->d_stream.total_in & 0xFF; + soap->z_buf[5] = (soap->d_stream.total_in >> 8) & 0xFF; + soap->z_buf[6] = (soap->d_stream.total_in >> 16) & 0xFF; + soap->z_buf[7] = (soap->d_stream.total_in >> 24) & 0xFF; + if (soap_flush_raw(soap, soap->z_buf, 8)) + return soap->error; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip crc32=%lu\n", (unsigned long)soap->z_crc)); +#endif + } +#endif + if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) + { char *p; +#ifndef WITH_NOHTTP + if (!(soap->mode & SOAP_ENC_XML)) + { soap->mode--; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending buffered message of length %u\n", (unsigned int)soap->blist->size)); + if (soap->status >= SOAP_POST) + soap->error = soap->fpost(soap, soap->endpoint, soap->host, soap->port, soap->path, soap->action, soap->blist->size); + else if (soap->status != SOAP_STOP) + soap->error = soap->fresponse(soap, soap->status, soap->blist->size); + if (soap->error || soap_flush(soap)) + return soap->error; + soap->mode++; + } +#endif + for (p = soap_first_block(soap); p; p = soap_next_block(soap)) + { DBGMSG(SENT, p, soap_block_size(soap)); + if ((soap->error = soap->fsend(soap, p, soap_block_size(soap)))) + { soap_end_block(soap); + return soap->error; + } + } + soap_end_block(soap); + } +#ifndef WITH_LEANER + else if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) + { DBGMSG(SENT, "\r\n0\r\n\r\n", 7); + if ((soap->error = soap->fsend(soap, "\r\n0\r\n\r\n", 7))) + return soap->error; + } +#endif + } +#ifdef WITH_TCPFIN +#ifdef WITH_OPENSSL + if (!soap->ssl && soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP)) + soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 1); /* Send TCP FIN */ +#else + if (soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP)) + soap->fshutdownsocket(soap, (SOAP_SOCKET)soap->socket, 1); /* Send TCP FIN */ +#endif +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of send phase\n")); + soap->omode &= ~SOAP_XML_SEC; + soap->count = 0; + soap->part = SOAP_END; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_end_recv(struct soap *soap) +{ soap->part = SOAP_END; +#ifndef WITH_LEANER + if ((soap->mode & SOAP_ENC_DIME) && soap_getdime(soap)) + return soap->error; + soap->dime.list = soap->dime.first; + soap->dime.first = NULL; + soap->dime.last = NULL; + /* Check if MIME attachments and mime-post-check flag is set, if set call soap_resolve() and return */ + if (soap->mode & SOAP_ENC_MIME) + { +#ifndef WITH_NOIDREF + if (soap->mode & SOAP_MIME_POSTCHECK) + { soap_resolve(soap); + return SOAP_OK; + } +#endif + if (soap_getmime(soap)) + return soap->error; + } + soap->mime.list = soap->mime.first; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = NULL; + if (soap->xlist) + { struct soap_multipart *content; + for (content = soap->mime.list; content; content = content->next) + soap_resolve_attachment(soap, content); + } +#endif + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "End of receive message ok\n")); +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { soap->mode &= ~SOAP_ENC_ZLIB; + memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN); + soap->bufidx = (char*)soap->d_stream.next_in - soap->z_buf; + soap->buflen = soap->z_buflen; + soap->zlib_state = SOAP_ZLIB_NONE; + if (inflateEnd(&soap->d_stream) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; +#ifdef WITH_GZIP + if (soap->zlib_in == SOAP_ZLIB_GZIP) + { soap_wchar c; + short i; + for (i = 0; i < 8; i++) + { if ((int)(c = soap_getchar(soap)) == EOF) + return soap->error = SOAP_EOF; + soap->z_buf[i] = (char)c; + } + if (soap->z_crc != ((uLong)(unsigned char)soap->z_buf[0] | ((uLong)(unsigned char)soap->z_buf[1] << 8) | ((uLong)(unsigned char)soap->z_buf[2] << 16) | ((uLong)(unsigned char)soap->z_buf[3] << 24))) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: crc check failed, message corrupted? (crc32=%lu)\n", (unsigned long)soap->z_crc)); + return soap->error = SOAP_ZLIB_ERROR; + } + if (soap->d_stream.total_out != ((uLong)(unsigned char)soap->z_buf[4] | ((uLong)(unsigned char)soap->z_buf[5] << 8) | ((uLong)(unsigned char)soap->z_buf[6] << 16) | ((uLong)(unsigned char)soap->z_buf[7] << 24))) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: incorrect message length\n")); + return soap->error = SOAP_ZLIB_ERROR; + } + } +#endif + } +#endif + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) + while ((int)soap_getchar(soap) != EOF) /* advance to last chunk */ + ; + if (soap->fdisconnect && (soap->error = soap->fdisconnect(soap))) + return soap->error; +#ifndef WITH_NOIDREF + if (soap_resolve(soap)) + return soap->error; +#endif +#ifndef WITH_LEANER + if (soap->xlist) + { if (soap->mode & SOAP_ENC_MTOM) + return soap->error = SOAP_MIME_HREF; + return soap->error = SOAP_DIME_HREF; + } +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_free_temp(struct soap *soap) +{ register struct Namespace *ns; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free namespace stack\n")); + while (soap->nlist) + { register struct soap_nlist *np = soap->nlist->next; + SOAP_FREE(soap, soap->nlist); + soap->nlist = np; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free any remaining temp blocks\n")); + while (soap->blist) + soap_end_block(soap); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute storage\n")); + while (soap->attributes) + { register struct soap_attribute *tp = soap->attributes->next; + if (soap->attributes->value) + SOAP_FREE(soap, soap->attributes->value); + SOAP_FREE(soap, soap->attributes); + soap->attributes = tp; + } +#ifdef WITH_FAST + if (soap->labbuf) + SOAP_FREE(soap, soap->labbuf); + soap->labbuf = NULL; + soap->lablen = 0; + soap->labidx = 0; +#endif + ns = soap->local_namespaces; + if (ns) + { for (; ns->id; ns++) + { if (ns->out) + { if (soap->encodingStyle == ns->out) + soap->encodingStyle = SOAP_STR_EOS; + SOAP_FREE(soap, ns->out); + ns->out = NULL; + } + if (soap->encodingStyle == ns->ns) + soap->encodingStyle = SOAP_STR_EOS; + } + SOAP_FREE(soap, soap->local_namespaces); + soap->local_namespaces = NULL; + } +#ifndef WITH_LEANER + while (soap->xlist) + { struct soap_xlist *xp = soap->xlist->next; + SOAP_FREE(soap, soap->xlist); + soap->xlist = xp; + } +#endif +#ifndef WITH_NOIDREF + soap_free_pht(soap); + soap_free_iht(soap); +#endif +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +static void +soap_init_logs(struct soap *soap) +{ int i; + for (i = 0; i < SOAP_MAXLOGS; i++) + { soap->logfile[i] = NULL; + soap->fdebug[i] = NULL; + } +} +#endif + +/******************************************************************************/ +#if !defined(WITH_LEAN) || defined(SOAP_DEBUG) +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_open_logfile(struct soap *soap, int i) +{ if (soap->logfile[i]) + soap->fdebug[i] = fopen(soap->logfile[i], i < 2 ? "ab" : "a"); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +static void +soap_close_logfile(struct soap *soap, int i) +{ if (soap->fdebug[i]) + { fclose(soap->fdebug[i]); + soap->fdebug[i] = NULL; + } +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_close_logfiles(struct soap *soap) +{ int i; + for (i = 0; i < SOAP_MAXLOGS; i++) + soap_close_logfile(soap, i); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +static void +soap_set_logfile(struct soap *soap, int i, const char *logfile) +{ const char *s; + char *t = NULL; + soap_close_logfile(soap, i); + s = soap->logfile[i]; + soap->logfile[i] = logfile; + if (s) + SOAP_FREE(soap, (void*)s); + if (logfile) + if ((t = (char*)SOAP_MALLOC(soap, strlen(logfile) + 1))) + strcpy(t, logfile); + soap->logfile[i] = t; +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_recv_logfile(struct soap *soap, const char *logfile) +{ soap_set_logfile(soap, SOAP_INDEX_RECV, logfile); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_sent_logfile(struct soap *soap, const char *logfile) +{ soap_set_logfile(soap, SOAP_INDEX_SENT, logfile); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_test_logfile(struct soap *soap, const char *logfile) +{ soap_set_logfile(soap, SOAP_INDEX_TEST, logfile); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_copy(struct soap *soap) +{ return soap_copy_context((struct soap*)malloc(sizeof(struct soap)), soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_copy_context(struct soap *copy, struct soap *soap) +{ if (soap_check_state(soap)) + return NULL; + if (copy) + { register struct soap_plugin *p; + memcpy(copy, soap, sizeof(struct soap)); + copy->state = SOAP_COPY; + copy->error = SOAP_OK; + copy->userid = NULL; + copy->passwd = NULL; + copy->nlist = NULL; + copy->blist = NULL; + copy->clist = NULL; + copy->alist = NULL; + copy->attributes = NULL; + copy->labbuf = NULL; + copy->lablen = 0; + copy->labidx = 0; +#ifdef SOAP_DEBUG + soap_init_mht(copy); +#endif + copy->local_namespaces = NULL; +#ifndef WITH_NOIDREF + soap_init_iht(copy); + soap_init_pht(copy); +#endif + copy->header = NULL; + copy->fault = NULL; + copy->action = NULL; +#ifndef WITH_LEAN +#ifdef WITH_COOKIES + copy->cookies = soap_copy_cookies(copy, soap); +#else + copy->cookies = NULL; +#endif +#endif +#ifdef SOAP_DEBUG + soap_init_logs(copy); + soap_set_recv_logfile(copy, soap->logfile[SOAP_INDEX_RECV]); + soap_set_sent_logfile(copy, soap->logfile[SOAP_INDEX_SENT]); + soap_set_test_logfile(copy, soap->logfile[SOAP_INDEX_TEST]); +#endif + copy->plugins = NULL; + for (p = soap->plugins; p; p = p->next) + { register struct soap_plugin *q = (struct soap_plugin*)SOAP_MALLOC(copy, sizeof(struct soap_plugin)); + if (!q) + return NULL; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying plugin '%s'\n", p->id)); + *q = *p; + if (p->fcopy && (soap->error = p->fcopy(copy, q, p))) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not copy plugin '%s'\n", p->id)); + SOAP_FREE(copy, q); + return NULL; + } + q->next = copy->plugins; + copy->plugins = q; + } + } + else + soap->error = SOAP_EOM; + return copy; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_copy_stream(struct soap *copy, struct soap *soap) +{ copy->mode = soap->mode; + copy->imode = soap->imode; + copy->omode = soap->omode; + copy->socket = soap->socket; + copy->recv_timeout = soap->recv_timeout; + copy->send_timeout = soap->send_timeout; +#if defined(__cplusplus) && !defined(WITH_LEAN) + copy->os = soap->os; + copy->is = soap->is; +#endif + copy->sendfd = soap->sendfd; + copy->recvfd = soap->recvfd; + copy->bufidx = soap->bufidx; + copy->buflen = soap->buflen; + copy->ahead = soap->ahead; + copy->cdata = soap->cdata; + copy->chunksize = soap->chunksize; + copy->chunkbuflen = soap->chunkbuflen; + copy->keep_alive = soap->keep_alive; + copy->max_keep_alive = soap->max_keep_alive; +#ifndef WITH_NOIO + copy->peer = soap->peer; + copy->peerlen = soap->peerlen; +#endif +#ifdef WITH_OPENSSL + copy->bio = soap->bio; + copy->ssl = soap->ssl; + copy->ctx = soap->ctx; +#endif +#ifdef WITH_ZLIB + copy->zlib_state = soap->zlib_state; + copy->zlib_in = soap->zlib_in; + copy->zlib_out = soap->zlib_out; + copy->d_stream = soap->d_stream; + copy->z_buflen = soap->z_buflen; + copy->z_level = soap->z_level; + copy->z_crc = soap->z_crc; + copy->z_ratio_in = soap->z_ratio_in; + copy->z_ratio_out = soap->z_ratio_out; + memcpy(copy->z_buf, soap->z_buf, sizeof(soap->z_buf)); +#endif + memcpy(copy->buf, soap->buf, sizeof(soap->buf)); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_init(struct soap *soap) +{ soap->state = SOAP_INIT; + soap->version = 0; + soap_imode(soap, SOAP_IO_DEFAULT); + soap_omode(soap, SOAP_IO_DEFAULT); + soap->plugins = NULL; + soap->user = NULL; + soap->userid = NULL; + soap->passwd = NULL; +#ifndef WITH_NOHTTP + soap->fpost = http_post; + soap->fget = http_get; + soap->fform = NULL; + soap->fposthdr = http_post_header; + soap->fresponse = http_response; + soap->fparse = http_parse; + soap->fparsehdr = http_parse_header; +#endif + soap->fheader = NULL; + soap->fconnect = NULL; + soap->fdisconnect = NULL; +#ifndef WITH_NOIO +#ifndef WITH_IPV6 + soap->fresolve = tcp_gethost; +#else + soap->fresolve = NULL; +#endif + soap->faccept = tcp_accept; + soap->fopen = tcp_connect; + soap->fclose = tcp_disconnect; + soap->fclosesocket = tcp_closesocket; + soap->fshutdownsocket = tcp_shutdownsocket; + soap->fsend = fsend; + soap->frecv = frecv; + soap->fpoll = soap_poll; +#else + soap->fopen = NULL; + soap->fclose = NULL; + soap->fpoll = NULL; +#endif + soap->fseterror = NULL; + soap->fignore = NULL; + soap->fserveloop = NULL; + soap->fplugin = fplugin; + soap->fmalloc = NULL; +#ifndef WITH_LEANER + soap->fprepareinit = NULL; + soap->fpreparesend = NULL; + soap->fpreparerecv = NULL; + soap->fpreparefinal = NULL; + soap->fdimereadopen = NULL; + soap->fdimewriteopen = NULL; + soap->fdimereadclose = NULL; + soap->fdimewriteclose = NULL; + soap->fdimeread = NULL; + soap->fdimewrite = NULL; + soap->fmimereadopen = NULL; + soap->fmimewriteopen = NULL; + soap->fmimereadclose = NULL; + soap->fmimewriteclose = NULL; + soap->fmimeread = NULL; + soap->fmimewrite = NULL; +#endif + soap->float_format = "%G"; + soap->double_format = "%lG"; + soap->dime_id_format = "cid:id%d"; /* default DIME id format */ + soap->http_version = "1.1"; + soap->proxy_http_version = "1.0"; + soap->http_content = NULL; + soap->actor = NULL; + soap->max_keep_alive = SOAP_MAXKEEPALIVE; + soap->keep_alive = 0; + soap->recv_timeout = 0; + soap->send_timeout = 0; + soap->connect_timeout = 0; + soap->accept_timeout = 0; + soap->socket_flags = 0; + soap->connect_flags = 0; + soap->bind_flags = 0; + soap->accept_flags = 0; + soap->ip = 0; + soap->labbuf = NULL; + soap->lablen = 0; + soap->labidx = 0; + soap->encodingStyle = SOAP_STR_EOS; +#ifndef WITH_NONAMESPACES + soap->namespaces = namespaces; +#else + soap->namespaces = NULL; +#endif + soap->local_namespaces = NULL; + soap->nlist = NULL; + soap->blist = NULL; + soap->clist = NULL; + soap->alist = NULL; + soap->attributes = NULL; + soap->header = NULL; + soap->fault = NULL; + soap->master = SOAP_INVALID_SOCKET; + soap->socket = SOAP_INVALID_SOCKET; + soap->os = NULL; + soap->is = NULL; +#ifndef WITH_LEANER + soap->dom = NULL; + soap->dime.list = NULL; + soap->dime.first = NULL; + soap->dime.last = NULL; + soap->mime.list = NULL; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = NULL; + soap->mime.start = NULL; + soap->xlist = NULL; +#endif +#ifndef UNDER_CE + soap->recvfd = 0; + soap->sendfd = 1; +#else + soap->recvfd = stdin; + soap->sendfd = stdout; +#endif + soap->host[0] = '\0'; + soap->port = 0; + soap->action = NULL; + soap->proxy_host = NULL; + soap->proxy_port = 8080; + soap->proxy_userid = NULL; + soap->proxy_passwd = NULL; + soap->authrealm = NULL; + soap->prolog = NULL; +#ifdef WITH_ZLIB + soap->zlib_state = SOAP_ZLIB_NONE; + soap->zlib_in = SOAP_ZLIB_NONE; + soap->zlib_out = SOAP_ZLIB_NONE; + soap->d_stream.zalloc = NULL; + soap->d_stream.zfree = NULL; + soap->d_stream.opaque = NULL; + soap->z_level = 6; +#endif +#ifndef WITH_LEAN + soap->c14ninclude = NULL; + soap->c14nexclude = NULL; + soap->cookies = NULL; + soap->cookie_domain = NULL; + soap->cookie_path = NULL; + soap->cookie_max = 32; +#endif +#ifdef SOAP_DEBUG + soap_init_mht(soap); + soap_init_logs(soap); +#endif +#ifdef WMW_RPM_IO + soap->rpmreqid = NULL; +#endif +#ifdef PALM + palmNetLibOpen(); +#endif +#ifndef WITH_NOIDREF + soap_init_iht(soap); + soap_init_pht(soap); +#endif +#ifdef SOAP_DEBUG + soap_set_recv_logfile(soap, "RECV.log"); + soap_set_sent_logfile(soap, "SENT.log"); + soap_set_test_logfile(soap, "TEST.log"); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing context\n")); +#endif +#ifdef WITH_OPENSSL + if (!ssl_init_done) + { soap_ssl_init(); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing OpenSSL, version=%ld\n", (long)OPENSSL_VERSION_NUMBER)); + } + soap->fsslauth = ssl_auth_init; + soap->fsslverify = ssl_verify_callback; + soap->bio = NULL; + soap->ssl = NULL; + soap->ctx = NULL; + soap->ssl_flags = SOAP_SSL_DEFAULT; + soap->keyfile = NULL; + soap->password = NULL; + soap->dhfile = NULL; + soap->cafile = NULL; + soap->capath = NULL; + soap->crlfile = NULL; + soap->randfile = NULL; + soap->session = NULL; +#endif + soap_begin(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_init1(struct soap *soap, soap_mode mode) +{ soap_init2(soap, mode, mode); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_init2(struct soap *soap, soap_mode imode, soap_mode omode) +{ soap_init(soap); + soap_imode(soap, imode); + soap_omode(soap, omode); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_begin(struct soap *soap) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reinitializing context\n")); + if (!soap->keep_alive) + { soap->buflen = 0; + soap->bufidx = 0; + } + soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0); + soap->null = 0; + soap->position = 0; + soap->encoding = 0; + soap->mustUnderstand = 0; + soap->mode = 0; + soap->ns = 0; + soap->part = SOAP_END; + soap->alloced = 0; + soap->count = 0; + soap->length = 0; + soap->cdata = 0; + soap->error = SOAP_OK; + soap->peeked = 0; + soap->ahead = 0; + soap->idnum = 0; + soap->level = 0; + soap->endpoint[0] = '\0'; +#ifndef WITH_LEANER + soap->dime.chunksize = 0; + soap->dime.buflen = 0; +#endif + soap_free_temp(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_end(struct soap *soap) +{ if (soap_check_state(soap)) + return; + soap_free_temp(soap); + soap_dealloc(soap, NULL); + while (soap->clist) + { register struct soap_clist *cp = soap->clist->next; + SOAP_FREE(soap, soap->clist); + soap->clist = cp; + } + soap_closesock(soap); +#ifdef SOAP_DEBUG + soap_close_logfiles(soap); +#endif +#ifdef PALM + palmNetLibClose(); +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_namespaces(struct soap *soap, const struct Namespace *p) +{ register struct Namespace *ns = soap->local_namespaces; + register struct soap_nlist *np, *nq, *nr; + register unsigned int level = soap->level; + soap->namespaces = p; + soap->local_namespaces = NULL; + soap_set_local_namespaces(soap); + /* reverse the namespace list */ + np = soap->nlist; + soap->nlist = NULL; + if (np) + { nq = np->next; + np->next = NULL; + while (nq) + { nr = nq->next; + nq->next = np; + np = nq; + nq = nr; + } + } + /* then push on new stack */ + while (np) + { register const char *s; + soap->level = np->level; /* preserve element nesting level */ + s = np->ns; + if (!s && np->index >= 0 && ns) + { s = ns[np->index].out; + if (!s) + s = ns[np->index].ns; + } + if (s && soap_push_namespace(soap, np->id, s)) + return soap->error; + nq = np; + np = np->next; + SOAP_FREE(soap, nq); + } + if (ns) + { register int i; + for (i = 0; ns[i].id; i++) + { if (ns[i].out) + { SOAP_FREE(soap, ns[i].out); + ns[i].out = NULL; + } + } + SOAP_FREE(soap, ns); + } + soap->level = level; /* restore level */ + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_local_namespaces(struct soap *soap) +{ if (soap->namespaces && !soap->local_namespaces) + { register const struct Namespace *ns1; + register struct Namespace *ns2; + register size_t n = 1; + for (ns1 = soap->namespaces; ns1->id; ns1++) + n++; + n *= sizeof(struct Namespace); + ns2 = (struct Namespace*)SOAP_MALLOC(soap, n); + if (ns2) + { memcpy(ns2, soap->namespaces, n); + if (ns2[0].ns) + { if (!strcmp(ns2[0].ns, soap_env1)) + soap->version = 1; + else + soap->version = 2; + } + soap->local_namespaces = ns2; + } + } +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +#ifndef PALM_1 +SOAP_FMAC1 +const char * +SOAP_FMAC2 +soap_strsearch(const char *big, const char *little) +{ size_t n = strlen(little); + const char *s = big; + while (s) + { if (!strncmp(s, little, n) && (s[n] == '\0' || s[n] == ' ')) + return s; + s = strchr(s, ' '); + if (s) + s++; + } + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +#ifndef PALM_1 +SOAP_FMAC1 +struct soap_nlist * +SOAP_FMAC2 +soap_lookup_ns(struct soap *soap, const char *tag, size_t n) +{ register struct soap_nlist *np; + for (np = soap->nlist; np; np = np->next) + { if (!strncmp(np->id, tag, n) && !np->id[n]) + return np; + } + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static struct soap_nlist * +soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized) +{ register struct soap_nlist *np; + size_t n, k; + if (soap_strsearch(soap->c14nexclude, id)) + return NULL; + if (!utilized) + { for (np = soap->nlist; np; np = np->next) + { if (!strcmp(np->id, id) && (!np->ns || !strcmp(np->ns, ns))) + break; + } + if (np) + { if ((np->level < soap->level || !np->ns) && np->index == 1) + utilized = 1; + else + return NULL; + } + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Adding namespace binding (level=%u) '%s' '%s' utilized=%d\n", soap->level, id, ns?ns:"(null)", utilized)); + n = strlen(id); + if (ns) + k = strlen(ns); + else + k = 0; + np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k + 1); + if (!np) + { soap->error = SOAP_EOM; + return NULL; + } + np->next = soap->nlist; + soap->nlist = np; + strcpy(np->id, id); + if (ns) + { np->ns = np->id + n + 1; + strcpy(np->ns, ns); + } + else + np->ns = NULL; + np->level = soap->level; + np->index = utilized; + return np; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static void +soap_utilize_ns(struct soap *soap, const char *tag, size_t n) +{ register struct soap_nlist *np = soap_lookup_ns(soap, tag, n); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Utilizing namespace of '%s'\n", tag)); + if (np) + { if (np->index == 0) + soap_push_ns(soap, np->id, np->ns, 1); + } + else if (strncmp(tag, "xml", 3)) + { strncpy(soap->tmpbuf, tag, n); + soap->tmpbuf[n] = '\0'; + soap_push_ns(soap, soap->tmpbuf, NULL, 1); + } +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static void +soap_pop_ns(struct soap *soap) +{ soap_pop_namespace(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element(struct soap *soap, const char *tag, int id, const char *type) +{ +#ifdef WITH_XMLNS + register const char *s; +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element begin tag='%s' id='%d' type='%s'\n", tag, id, type?type:"")); +#ifdef WITH_DOM + if (soap->part == SOAP_BEGIN_SECURITY && (soap->mode & SOAP_XML_CANONICAL) && !(soap->mode & SOAP_DOM_ASIS)) + { register struct soap_nlist *np; + /* wsu:Id found: clear xmlns renderings, so re-emit them for exc-c14n */ + for (np = soap->nlist; np; np = np->next) + { if (np->index == 2) + np->index = 0; + } + } + if (soap->mode & SOAP_XML_DOM) + { register struct soap_dom_element *elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element)); + if (!elt) + return soap->error = SOAP_EOM; + elt->soap = soap; + elt->next = NULL; + elt->prnt = soap->dom; + elt->name = soap_strdup(soap, tag); + elt->elts = NULL; + elt->atts = NULL; + elt->nstr = NULL; + elt->data = NULL; + elt->wide = NULL; + elt->node = NULL; + elt->type = 0; + elt->head = NULL; + elt->tail = NULL; + if (soap->dom) + { struct soap_dom_element *p = soap->dom->elts; + if (p) + { while (p->next) + p = p->next; + p->next = elt; + } + else + soap->dom->elts = elt; + } + soap->dom = elt; + } + else + { +#endif + soap->level++; +#ifndef WITH_LEAN + if (!soap->ns) + { if (!(soap->mode & SOAP_XML_CANONICAL) + && soap_send(soap, soap->prolog ? soap->prolog : "\n")) + return soap->error; + } + else if (soap->mode & SOAP_XML_INDENT) + { if (soap->ns == 1 && soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1)) + return soap->error; + soap->body = 1; + } +#endif +#ifdef WITH_XMLNS + s = strchr(tag, ':'); + if (s && strncmp(tag, "SOAP-ENV", s - tag)) + { struct Namespace *ns = soap->local_namespaces; + size_t n = s - tag; + if (soap_send_raw(soap, "<", 1) + || soap_send(soap, s + 1)) + return soap->error; + if (soap->nlist && !strncmp(soap->nlist->id, tag, n) && !soap->nlist->id[n]) + ns = NULL; + for (; ns && ns->id; ns++) + { if (*ns->id && (ns->out || ns->ns) && !strncmp(ns->id, tag, n) && !ns->id[n]) + { soap_push_ns(soap, ns->id, ns->out ? ns->out : ns->ns, 0); + if (soap_attribute(soap, "xmlns", ns->out ? ns->out : ns->ns)) + return soap->error; + break; + } + } + } + else +#endif + if (soap_send_raw(soap, "<", 1) + || soap_send(soap, tag)) + return soap->error; +#ifdef WITH_DOM + } +#endif + if (!soap->ns) + { struct Namespace *ns; + for (ns = soap->local_namespaces; ns && ns->id; ns++) + { if (*ns->id && (ns->out || ns->ns)) + { sprintf(soap->tmpbuf, "xmlns:%s", ns->id); + if (soap_attribute(soap, soap->tmpbuf, ns->out ? ns->out : ns->ns)) + return soap->error; + } + } + } + soap->ns = 1; /* start with 0 or 2, but should be one to continue */ +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { const char *t = strchr(tag, ':'); + if (t) + soap_utilize_ns(soap, tag, t - tag); + } +#endif + if (id > 0) + { sprintf(soap->tmpbuf, "_%d", id); + if (soap_attribute(soap, "id", soap->tmpbuf)) + return soap->error; + } + if (type && *type && (!(soap->mode & SOAP_XML_SEC) || soap->part == SOAP_IN_BODY)) + { if (soap_attribute(soap, "xsi:type", type)) + return soap->error; +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { const char *t = strchr(type, ':'); + if (t) + soap_utilize_ns(soap, type, t - type); + } +#endif + } + if (soap->null && soap->position > 0) + { register int i; + sprintf(soap->tmpbuf, "[%d", soap->positions[0]); + for (i = 1; i < soap->position; i++) + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), ",%d", soap->positions[i]); + strcat(soap->tmpbuf, "]"); + if (soap_attribute(soap, "SOAP-ENC:position", soap->tmpbuf)) + return soap->error; + } + if (soap->mustUnderstand) + { if (soap->actor && *soap->actor) + { if (soap_attribute(soap, soap->version == 2 ? "SOAP-ENV:role" : "SOAP-ENV:actor", soap->actor)) + return soap->error; + } + if (soap_attribute(soap, "SOAP-ENV:mustUnderstand", soap->version == 2 ? "true" : "1")) + return soap->error; + soap->mustUnderstand = 0; + } + if (soap->encoding) + { if (soap->encodingStyle && soap->local_namespaces) + { if (!*soap->encodingStyle) + { if (soap->local_namespaces[1].out) + soap->encodingStyle = soap->local_namespaces[1].out; + else + soap->encodingStyle = soap->local_namespaces[1].ns; + } + if (soap_attribute(soap, "SOAP-ENV:encodingStyle", soap->encodingStyle)) + return soap->error; + } + soap->encoding = 0; + } + soap->null = 0; + soap->position = 0; + if (soap->part == SOAP_BEGIN_SECURITY && (soap->mode & SOAP_XML_CANONICAL)) + soap->part = SOAP_IN_SECURITY; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_begin_out(struct soap *soap, const char *tag, int id, const char *type) +{ if (*tag == '-') + return SOAP_OK; + if (soap_element(soap, tag, id, type)) + return soap->error; + return soap_element_start_end_out(soap, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +#ifndef HAVE_STRRCHR +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_strrchr(const char *s, int t) +{ register char *r = NULL; + while (*s) + if (*s++ == t) + r = (char*)s - 1; + return r; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +#ifndef HAVE_STRTOL +SOAP_FMAC1 +long +SOAP_FMAC2 +soap_strtol(const char *s, char **t, int b) +{ register long n = 0; + register int c; + while (*s > 0 && *s <= 32) + s++; + if (b == 10) + { short neg = 0; + if (*s == '-') + { s++; + neg = 1; + } + else if (*s == '+') + s++; + while ((c = *s) && c >= '0' && c <= '9') + { if (n >= 214748364 && (n > 214748364 || c >= '8')) + break; + n *= 10; + n += c - '0'; + s++; + } + if (neg) + n = -n; + } + else /* b == 16 and value is always positive */ + { while ((c = *s)) + { if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'F') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'f') + c -= 'a' - 10; + if (n > 0x07FFFFFF) + break; + n <<= 4; + n += c; + s++; + } + } + if (t) + *t = (char*)s; + return n; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +#ifndef HAVE_STRTOUL +SOAP_FMAC1 +unsigned long +SOAP_FMAC2 +soap_strtoul(const char *s, char **t, int b) +{ unsigned long n = 0; + register int c; + while (*s > 0 && *s <= 32) + s++; + if (b == 10) + { if (*s == '+') + s++; + while ((c = *s) && c >= '0' && c <= '9') + { if (n >= 429496729 && (n > 429496729 || c >= '6')) + break; + n *= 10; + n += c - '0'; + s++; + } + } + else /* b == 16 */ + { while ((c = *s)) + { if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'F') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'f') + c -= 'a' - 10; + if (n > 0x0FFFFFFF) + break; + n <<= 4; + n += c; + s++; + } + } + if (t) + *t = (char*)s; + return n; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_array_begin_out(struct soap *soap, const char *tag, int id, const char *type, const char *offset) +{ if (soap_element(soap, tag, id, "SOAP-ENC:Array")) + return soap->error; + if (soap->version == 2) + { const char *s; + s = soap_strrchr(type, '['); + if ((size_t)(s - type) < sizeof(soap->tmpbuf)) + { strncpy(soap->tmpbuf, type, s - type); + soap->tmpbuf[s - type] = '\0'; + if (type && *type && (soap_attribute(soap, "SOAP-ENC:itemType", soap->tmpbuf))) + return soap->error; + if (s && (soap_attribute(soap, "SOAP-ENC:arraySize", s + 1))) + return soap->error; + } + } + else + { if (offset && (soap_attribute(soap, "SOAP-ENC:offset", offset))) + return soap->error; + if (type && *type && (soap_attribute(soap, "SOAP-ENC:arrayType", type))) + return soap->error; + } +#ifndef WITH_LEAN + if (type && *type && (soap->mode & SOAP_XML_CANONICAL)) + { const char *s = strchr(type, ':'); + if (s) + soap_utilize_ns(soap, type, s - type); + } +#endif + return soap_element_start_end_out(soap, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_start_end_out(struct soap *soap, const char *tag) +{ register struct soap_attribute *tp; +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { struct soap_nlist *np; + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible && tp->name) + { const char *s = strchr(tp->name, ':'); + if (s) + soap_utilize_ns(soap, tp->name, s - tp->name); + } + } + for (np = soap->nlist; np; np = np->next) + { if (np->index == 1 && np->ns) + { sprintf(soap->tmpbuf, "xmlns:%s", np->id); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enabling utilized binding (level=%u) %s='%s'\n", np->level, soap->tmpbuf, np->ns)); + soap_set_attr(soap, soap->tmpbuf, np->ns); + np->index = 2; + } + } + } +#endif +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { register struct soap_dom_attribute **att; + att = &soap->dom->atts; + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible) + { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); + if (!*att) + return soap->error = SOAP_EOM; + (*att)->next = NULL; + (*att)->nstr = NULL; + (*att)->name = soap_strdup(soap, tp->name); + (*att)->data = soap_strdup(soap, tp->value); + (*att)->wide = NULL; + (*att)->soap = soap; + att = &(*att)->next; + tp->visible = 0; + } + } + return SOAP_OK; + } +#endif + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible) + { +#ifdef WITH_XMLNS + const char *s = strchr(tp->name, ':'); + if (s) + { size_t n = s - tp->name; + if (soap->nlist && !strncmp(soap->nlist->id, tp->name, n) && !soap->nlist->id[n]) + s++; + else + s = tp->name; + if (soap_send(soap, " ") || soap_send(soap, s)) + return soap->error; + } + else +#endif + if (soap_send(soap, " ") || soap_send(soap, tp->name)) + return soap->error; + if (tp->visible == 2 && tp->value) + if (soap_send_raw(soap, "=\"", 2) + || soap_string_out(soap, tp->value, 1) + || soap_send_raw(soap, "\"", 1)) + return soap->error; + tp->visible = 0; + } + } + if (tag) + { +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { if (soap_send_raw(soap, ">", 1) + || soap_element_end_out(soap, tag)) + return soap->error; + return SOAP_OK; + } +#endif + soap->level--; /* decrement level just before /> */ + if (soap_send_raw(soap, "/>", 2)) + return soap->error; + return SOAP_OK; + } + return soap_send_raw(soap, ">", 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_end_out(struct soap *soap, const char *tag) +{ if (*tag == '-') + return SOAP_OK; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element ending tag='%s'\n", tag)); +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { if (soap->dom->prnt) + soap->dom = soap->dom->prnt; + return SOAP_OK; + } +#endif +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + soap_pop_ns(soap); + if (soap->mode & SOAP_XML_INDENT) + { if (!soap->body) + { if (soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1)) + return soap->error; + } + soap->body = 0; + } +#endif +#ifdef WITH_XMLNS + { const char *s = strchr(tag, ':'); + if (s && strncmp(tag, "SOAP-ENV", s - tag)) + { soap_pop_ns(soap); + tag = s + 1; + } + } +#endif + if (soap_send_raw(soap, "error; + soap->level--; /* decrement level just before > */ + return soap_send_raw(soap, ">", 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_ref(struct soap *soap, const char *tag, int id, int href) +{ register int n = 0; + const char *s = "href"; + if (soap->version == 2) + { s = "SOAP-ENC:ref"; + n = 1; + } + sprintf(soap->href, "#_%d", href); + return soap_element_href(soap, tag, id, s, soap->href + n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_href(struct soap *soap, const char *tag, int id, const char *ref, const char *val) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element '%s' reference %s='%s'\n", tag, ref, val)); + if (soap_element(soap, tag, id, NULL) + || soap_attribute(soap, ref, val) + || soap_element_start_end_out(soap, tag)) + return soap->error; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_null(struct soap *soap, const char *tag, int id, const char *type) +{ struct soap_attribute *tp; + for (tp = soap->attributes; tp; tp = tp->next) + if (tp->visible) + break; + if (tp || (soap->version == 2 && soap->position > 0) || id > 0 || (soap->mode & SOAP_XML_NIL)) + { if (soap_element(soap, tag, id, type)) + return soap->error; + if (soap->part != SOAP_IN_HEADER && soap->encodingStyle) + if (soap_attribute(soap, "xsi:nil", "true")) + return soap->error; + return soap_element_start_end_out(soap, tag); + } + soap->null = 1; + soap->position = 0; + soap->mustUnderstand = 0; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_id(struct soap *soap, const char *tag, int id, const void *p, const struct soap_array *a, int n, const char *type, int t) +{ if (!p || (a && !a->__ptr)) + { soap_element_null(soap, tag, id, type); + return -1; + } +#ifndef WITH_NOIDREF + if (soap->mode & SOAP_XML_TREE) + return 0; + if (id < 0) + { struct soap_plist *pp; + if (a) + id = soap_array_pointer_lookup(soap, p, a, n, t, &pp); + else + id = soap_pointer_lookup(soap, p, t, &pp); + if (id) + { if (soap_is_embedded(soap, pp)) + { soap_element_ref(soap, tag, 0, id); + return -1; + } + if (soap_is_single(soap, pp)) + return 0; + soap_set_embedded(soap, pp); + } + } + return id; +#else + return 0; +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_result(struct soap *soap, const char *tag) +{ if (soap->version == 2 && soap->encodingStyle) + if (soap_element(soap, "SOAP-RPC:result", 0, NULL) + || soap_attribute(soap, "xmlns:SOAP-RPC", soap_rpc) + || soap_element_start_end_out(soap, NULL) + || soap_string_out(soap, tag, 0) + || soap_element_end_out(soap, "SOAP-RPC:result")) + return soap->error; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_check_result(struct soap *soap, const char *tag) +{ if (soap->version == 2 && soap->encodingStyle) + { soap_instring(soap, ":result", NULL, NULL, 0, 2, -1, -1); + /* should compare tag to element's QName value? */ + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_attribute(struct soap *soap, const char *name, const char *value) +{ +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && !(soap->mode & SOAP_XML_CANONICAL) && soap->dom) + { register struct soap_dom_attribute *a = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); + a->next = soap->dom->atts; + a->nstr = NULL; + a->name = soap_strdup(soap, name); + a->data = soap_strdup(soap, value); + a->wide = NULL; + a->soap = soap; + soap->dom->atts = a; + return SOAP_OK; + } +#endif +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { /* TODO: consider using this code to handle default namespace bindings + if (!strncmp(name, "xmlns", 5) && (name[5] == ':' || name[5] == '\0')) + { if (name[5] == ':') + soap_push_ns(soap, name + 6, value, 0); + else + soap_push_ns(soap, "", value, 0); + } + */ + if (!strncmp(name, "xmlns:", 6)) + soap_push_ns(soap, name + 6, value, 0); + else if (soap_set_attr(soap, name, value)) + return soap->error; + } + else +#endif + { if (soap_send(soap, " ") || soap_send(soap, name)) + return soap->error; + if (value) + if (soap_send_raw(soap, "=\"", 2) + || soap_string_out(soap, value, 1) + || soap_send_raw(soap, "\"", 1)) + return soap->error; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_begin_in(struct soap *soap, const char *tag, int nillable, const char *type) +{ if (!soap_peek_element(soap)) + { if (soap->other) + return soap->error = SOAP_TAG_MISMATCH; + if (tag && *tag == '-') + return SOAP_OK; + if (!(soap->error = soap_match_tag(soap, soap->tag, tag))) + { soap->peeked = 0; + if (soap->body) + soap->level++; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:"" )); + if (!nillable && soap->null && (soap->mode & SOAP_XML_STRICT)) + return soap->error = SOAP_NULL; + if (type && *soap->type && soap_match_tag(soap, soap->type, type)) + return soap->error = SOAP_TYPE; + } + } + else if (soap->error == SOAP_NO_TAG && tag && *tag == '-') + soap->error = SOAP_OK; + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_end_in(struct soap *soap, const char *tag) +{ register soap_wchar c; + register char *s; + register int n = 0; + if (tag && *tag == '-') + return SOAP_OK; + if (soap->error == SOAP_NO_TAG) + soap->error = SOAP_OK; +#ifdef WITH_DOM + /* this whitespace or mixed content is not insignificant for DOM */ + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { if (!soap->peeked && !soap_string_in(soap, 3, -1, -1)) + return soap->error; + if (soap->dom->prnt) + soap->dom = soap->dom->prnt; + } +#endif + if (soap->peeked) + { if (*soap->tag) + n++; + soap->peeked = 0; + } + do + { while (((c = soap_get(soap)) != SOAP_TT)) + { if ((int)c == EOF) + return soap->error = SOAP_EOF; + if (c == SOAP_LT) + n++; + else if (c == '/') + { c = soap_get(soap); + if (c == SOAP_GT) + n--; + else + soap_unget(soap, c); + } + } + } while (n--); + s = soap->tag; + n = sizeof(soap->tag); + while (soap_notblank(c = soap_get(soap))) + { if (--n > 0) + *s++ = (char)c; + } + *s = '\0'; + if ((int)c == EOF) + return soap->error = SOAP_EOF; + while (soap_blank(c)) + c = soap_get(soap); + if (c != SOAP_GT) + return soap->error = SOAP_SYNTAX_ERROR; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:"")); + if (!tag || !*tag || !soap_match_tag(soap, soap->tag, tag)) + { soap->level--; + soap_pop_namespace(soap); + return SOAP_OK; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element tag name does not match\n")); + return soap->error = SOAP_SYNTAX_ERROR; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char * +SOAP_FMAC2 +soap_attr_value(struct soap *soap, const char *name, int flag) +{ register struct soap_attribute *tp; + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible && !soap_match_tag(soap, tp->name, name)) + break; + } + if (tp) + { if (flag == 2 && (soap->mode & SOAP_XML_STRICT)) + soap->error = SOAP_PROHIBITED; + else + return tp->value; + } + else if (flag == 1 && (soap->mode & SOAP_XML_STRICT)) + soap->error = SOAP_REQUIRED; + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_attr(struct soap *soap, const char *name, const char *value) +{ register struct soap_attribute *tp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set attribute %s='%s'\n", name, value?value:"")); + for (tp = soap->attributes; tp; tp = tp->next) + { if (!strcmp(tp->name, name)) + break; + } + if (!tp) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute %s\n", name)); + if (!(tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(name)))) + return soap->error = SOAP_EOM; + tp->ns = NULL; +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { struct soap_attribute **tpp = &soap->attributes; + const char *s = strchr(name, ':'); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inserting attribute %s for c14n\n", name)) + if (!strncmp(name, "xmlns", 5)) + { for (; *tpp; tpp = &(*tpp)->next) + if (strncmp((*tpp)->name, "xmlns", 5) || strcmp((*tpp)->name + 5, name + 5) > 0) + break; + } + else if (!s) + { for (; *tpp; tpp = &(*tpp)->next) + if (strncmp((*tpp)->name, "xmlns", 5) && ((*tpp)->ns || strcmp((*tpp)->name, name) > 0)) + break; + } + else + { int k; + for (; *tpp; tpp = &(*tpp)->next) + { if (!strncmp((*tpp)->name, "xmlns:", 6) && !strncmp((*tpp)->name + 6, name, s - name) && !(*tpp)->name[6 + s - name]) + { if (!tp->ns) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Canonicalization: prefix %s=%p (%s)\n", name, (*tpp)->ns, (*tpp)->ns)); + tp->ns = (*tpp)->ns; + } + } + else if (strncmp((*tpp)->name, "xmlns", 5) && (*tpp)->ns && tp->ns && ((k = strcmp((*tpp)->ns, tp->ns)) > 0 || (!k && strcmp((*tpp)->name, name) > 0))) + break; + } + } + tp->next = *tpp; + *tpp = tp; + } + else +#endif + { tp->next = soap->attributes; + soap->attributes = tp; + } + strcpy(tp->name, name); + tp->value = NULL; + } + else if (tp->visible) + { return SOAP_OK; + } + else if (value && tp->value && tp->size <= strlen(value)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute value of %s (free %p)\n", name, tp->value)); + SOAP_FREE(soap, tp->value); + tp->value = NULL; + tp->ns = NULL; + } + if (value) + { if (!tp->value) + { tp->size = strlen(value) + 1; + if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size))) + return soap->error = SOAP_EOM; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute value for %s (%p)\n", tp->name, tp->value)); + } + strcpy(tp->value, value); + if (!strncmp(tp->name, "xmlns:", 6)) + tp->ns = tp->value; + tp->visible = 2; +#ifndef WITH_LEAN + if (!strcmp(name, "wsu:Id")) + { soap->part = SOAP_BEGIN_SECURITY; + strncpy(soap->id, value, sizeof(soap->id)); + soap->id[sizeof(soap->id)-1] = '\0'; + } +#endif + } + else + tp->visible = 1; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_clr_attr(struct soap *soap) +{ register struct soap_attribute *tp; +#ifndef WITH_LEAN + if ((soap->mode & SOAP_XML_CANONICAL)) + { while (soap->attributes) + { tp = soap->attributes->next; + if (soap->attributes->value) + SOAP_FREE(soap, soap->attributes->value); + SOAP_FREE(soap, soap->attributes); + soap->attributes = tp; + } + } + else +#endif + { for (tp = soap->attributes; tp; tp = tp->next) + tp->visible = 0; + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +static int +soap_getattrval(struct soap *soap, char *s, size_t n, soap_wchar d) +{ register size_t i; + for (i = 0; i < n; i++) + { register soap_wchar c = soap_get(soap); + switch (c) + { + case SOAP_TT: + *s++ = '<'; + soap_unget(soap, '/'); + break; + case SOAP_LT: + *s++ = '<'; + break; + case SOAP_GT: + if (d == ' ') + { soap_unget(soap, c); + *s = '\0'; + return SOAP_OK; + } + *s++ = '>'; + break; + case SOAP_QT: + if (c == d) + { *s = '\0'; + return SOAP_OK; + } + *s++ = '"'; + break; + case SOAP_AP: + if (c == d) + { *s = '\0'; + return SOAP_OK; + } + *s++ = '\''; + break; + case '\t': + case '\n': + case '\r': + case ' ': + case '/': + if (d == ' ') + { soap_unget(soap, c); + *s = '\0'; + return SOAP_OK; + } + default: + if ((int)c == EOF) + return soap->error = SOAP_EOF; + *s++ = (char)c; + } + } + return soap->error = SOAP_EOM; +} +#endif + +/******************************************************************************/ +#ifdef WITH_FAST +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_store_lab(struct soap *soap, const char *s, size_t n) +{ soap->labidx = 0; + return soap_append_lab(soap, s, n); +} +#endif +#endif + +/******************************************************************************/ +#ifdef WITH_FAST +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_append_lab(struct soap *soap, const char *s, size_t n) +{ if (soap->labidx + n >= soap->lablen) + { register char *t = soap->labbuf; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enlarging look-aside buffer to append data, old size=%lu", (unsigned long)soap->lablen)); + if (soap->lablen == 0) + soap->lablen = SOAP_LABLEN; + while (soap->labidx + n >= soap->lablen) + soap->lablen <<= 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, ", new size=%lu\n", (unsigned long)soap->lablen)); + soap->labbuf = (char*)SOAP_MALLOC(soap, soap->lablen); + if (!soap->labbuf) + { if (t) + SOAP_FREE(soap, t); + return soap->error = SOAP_EOM; + } + if (t) + { memcpy(soap->labbuf, t, soap->labidx); + SOAP_FREE(soap, t); + } + } + if (s) + { memcpy(soap->labbuf + soap->labidx, s, n); + soap->labidx += n; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_peek_element(struct soap *soap) +{ +#ifdef WITH_DOM + register struct soap_dom_attribute **att = NULL; + register char *lead = NULL; +#endif + register struct soap_attribute *tp; + const char *t; + register char *s; + register soap_wchar c; + register int i; + if (soap->peeked) + { if (!*soap->tag) + return soap->error = SOAP_NO_TAG; + return SOAP_OK; + } + soap->peeked = 1; + c = soap_getutf8(soap); +#ifdef WITH_DOM + /* whitespace leading to start tag is not insignificant for DOM */ + if (soap_blank(c)) + { soap->labidx = 0; + do + { if (soap_append_lab(soap, NULL, 0)) + return SOAP_EOM; + s = soap->labbuf + soap->labidx; + i = soap->lablen - soap->labidx; + soap->labidx = soap->lablen; + while (soap_blank(c) && i--) + { *s++ = c; + c = soap_getutf8(soap); + } + } + while (soap_blank(c)); + *s = '\0'; + lead = soap_strdup(soap, soap->labbuf); + } +#else + while (soap_blank(c)) + c = soap_getutf8(soap); +#endif + if (c != SOAP_LT) + { *soap->tag = '\0'; + if ((int)c == EOF) + return soap->error = SOAP_EOF; + soap_unget(soap, c); +#ifdef WITH_DOM + /* whitespace leading to end tag is not insignificant for DOM */ + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + soap->dom->tail = soap_strdup(soap, lead); +#endif + return soap->error = SOAP_NO_TAG; + } + s = soap->tag; + do c = soap_get1(soap); + while (soap_blank(c)); + i = sizeof(soap->tag); + while (c != '>' && c != '/' && soap_notblank(c) && (int)c != EOF) + { if (--i > 0) + *s++ = (char)c; + c = soap_get1(soap); + } + while (soap_blank(c)) + c = soap_get1(soap); + *s = '\0'; + soap->id[0] = '\0'; + soap->href[0] = '\0'; + soap->type[0] = '\0'; + soap->arrayType[0] = '\0'; + soap->arraySize[0] = '\0'; + soap->arrayOffset[0] = '\0'; + soap->other = 0; + soap->root = -1; + soap->position = 0; + soap->null = 0; + soap->mustUnderstand = 0; +#ifdef WITH_DOM + if (soap->mode & SOAP_XML_DOM) + { register struct soap_dom_element *elt; + elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element)); + if (!elt) + return soap->error = SOAP_EOM; + elt->next = NULL; + elt->nstr = NULL; + elt->name = soap_strdup(soap, soap->tag); + elt->prnt = soap->dom; + elt->elts = NULL; + elt->atts = NULL; + elt->data = NULL; + elt->wide = NULL; + elt->type = 0; + elt->node = NULL; + elt->head = lead; + elt->tail = NULL; + elt->soap = soap; + if (soap->dom) + { struct soap_dom_element *p = soap->dom->elts; + if (p) + { while (p->next) + p = p->next; + p->next = elt; + } + else + soap->dom->elts = elt; + } + soap->dom = elt; + att = &elt->atts; + } +#endif + for (tp = soap->attributes; tp; tp = tp->next) + tp->visible = 0; + while ((int)c != EOF && c != '>' && c != '/') + { s = soap->tmpbuf; + i = sizeof(soap->tmpbuf); + while (c != '=' && c != '>' && c != '/' && soap_notblank(c) && (int)c != EOF) + { if (--i > 0) + *s++ = (char)c; + c = soap_get1(soap); + } + *s = '\0'; + if (i == sizeof(soap->tmpbuf)) + return soap->error = SOAP_SYNTAX_ERROR; +#ifdef WITH_DOM + /* add attribute name to dom */ + if (att) + { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); + if (!*att) + return soap->error = SOAP_EOM; + (*att)->next = NULL; + (*att)->nstr = NULL; + (*att)->name = soap_strdup(soap, soap->tmpbuf); + (*att)->data = NULL; + (*att)->wide = NULL; + (*att)->soap = soap; + } +#endif + if (!strncmp(soap->tmpbuf, "xmlns", 5)) + { if (soap->tmpbuf[5] == ':') + { soap->tmpbuf[5] = '\0'; + t = soap->tmpbuf + 6; + } + else if (soap->tmpbuf[5]) + t = NULL; + else + t = SOAP_STR_EOS; + } + else + t = NULL; + for (tp = soap->attributes; tp; tp = tp->next) + { if (!SOAP_STRCMP(tp->name, soap->tmpbuf)) + break; + } + if (!tp) + { tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(soap->tmpbuf)); + if (!tp) + return soap->error = SOAP_EOM; + strcpy(tp->name, soap->tmpbuf); + tp->value = NULL; + tp->size = 0; + tp->next = soap->attributes; + soap->attributes = tp; + } + while (soap_blank(c)) + c = soap_get1(soap); + if (c == '=') + { do c = soap_getutf8(soap); + while (soap_blank(c)); + if (c != SOAP_QT && c != SOAP_AP) + { soap_unget(soap, c); + c = ' '; /* blank delimiter */ + } + if (soap_getattrval(soap, tp->value, tp->size, c)) + { +#ifdef WITH_FAST + if (soap->error != SOAP_EOM) + return soap->error; + soap->error = SOAP_OK; + if (soap_store_lab(soap, tp->value, tp->size)) + return soap->error; + if (tp->value) + SOAP_FREE(soap, tp->value); + for (;;) + { if (soap_getattrval(soap, soap->labbuf + soap->labidx, soap->lablen - soap->labidx, c)) + { if (soap->error != SOAP_EOM) + return soap->error; + soap->error = SOAP_OK; + soap->labidx = soap->lablen; + if (soap_append_lab(soap, NULL, 0)) + return soap->error; + } + else + break; + } + if (soap->labidx) + tp->size = soap->lablen; + else + { tp->size = strlen(soap->labbuf) + 1; + if (tp->size < SOAP_LABLEN) + tp->size = SOAP_LABLEN; + } + if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size))) + return soap->error = SOAP_EOM; + strcpy(tp->value, soap->labbuf); +#else + size_t n; + if (soap->error != SOAP_EOM) + return soap->error; + soap->error = SOAP_OK; + if (soap_new_block(soap)) + return soap->error; + for (;;) + { if (!(s = (char*)soap_push_block(soap, SOAP_BLKLEN))) + return soap->error; + if (soap_getattrval(soap, s, SOAP_BLKLEN, c)) + { if (soap->error != SOAP_EOM) + return soap->error; + soap->error = SOAP_OK; + } + else + break; + } + n = tp->size + soap->blist->size; + if (!(s = (char*)SOAP_MALLOC(soap, n))) + return soap->error = SOAP_EOM; + if (tp->value) + { memcpy(s, tp->value, tp->size); + SOAP_FREE(soap, tp->value); + } + soap_save_block(soap, s + tp->size, 0); + tp->value = s; + tp->size = n; +#endif + } + do c = soap_get1(soap); + while (soap_blank(c)); + tp->visible = 2; /* seen this attribute w/ value */ +#ifdef WITH_DOM + if (att) + (*att)->data = soap_strdup(soap, tp->value); +#endif + } + else + tp->visible = 1; /* seen this attribute w/o value */ +#ifdef WITH_DOM + if (att) + att = &(*att)->next; +#endif + if (t && tp->value) + { if (soap_push_namespace(soap, t, tp->value)) + return soap->error; + tp->visible = 0; + } + } +#ifdef WITH_DOM + if (att) + { soap->dom->nstr = soap_current_namespace(soap, soap->tag); + for (att = &soap->dom->atts; *att; att = &(*att)->next) + (*att)->nstr = soap_current_namespace(soap, (*att)->name); + } +#endif + if ((int)c == EOF) + return soap->error = SOAP_EOF; + if (!(soap->body = (c != '/'))) + do c = soap_get1(soap); + while (soap_blank(c)); +#ifdef WITH_DOM + if (soap->mode & SOAP_XML_DOM) + { if (!soap->body && soap->dom->prnt) + soap->dom = soap->dom->prnt; + } +#endif + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible && tp->value) + { if (!strcmp(tp->name, "id")) + { if (soap->version > 0 + || (soap->mode & SOAP_XML_GRAPH)) + { *soap->id = '#'; + strncpy(soap->id + 1, tp->value, sizeof(soap->id) - 2); + soap->id[sizeof(soap->id)-1] = '\0'; + } + } + else if (!strcmp(tp->name, "href")) + { if (soap->version == 1 + || (soap->mode & SOAP_XML_GRAPH) + || (soap->mode & SOAP_ENC_MTOM)) + { strncpy(soap->href, tp->value, sizeof(soap->href) - 1); + soap->href[sizeof(soap->href)-1] = '\0'; + } + } + else if (!soap_match_tag(soap, tp->name, "xsi:type")) + { strncpy(soap->type, tp->value, sizeof(soap->type) - 1); + soap->type[sizeof(soap->type)-1] = '\0'; + } + else if ((!soap_match_tag(soap, tp->name, "xsi:null") + || !soap_match_tag(soap, tp->name, "xsi:nil")) + && (!strcmp(tp->value, "1") + || !strcmp(tp->value, "true"))) + { soap->null = 1; + } + else if (soap->version == 1) + { if (!soap_match_tag(soap, tp->name, "SOAP-ENC:arrayType")) + { s = soap_strrchr(tp->value, '['); + if (s && (size_t)(s - tp->value) < sizeof(soap->arrayType)) + { strncpy(soap->arrayType, tp->value, s - tp->value); + soap->arrayType[s - tp->value] = '\0'; + strncpy(soap->arraySize, s, sizeof(soap->arraySize) - 1); + } + else + strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1); + soap->arraySize[sizeof(soap->arrayType)-1] = '\0'; + soap->arrayType[sizeof(soap->arrayType)-1] = '\0'; + } + else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:offset")) + strncpy(soap->arrayOffset, tp->value, sizeof(soap->arrayOffset)); + else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:position")) + soap->position = soap_getposition(tp->value, soap->positions); + else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:root")) + soap->root = ((!strcmp(tp->value, "1") || !strcmp(tp->value, "true"))); + else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand") + && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true"))) + soap->mustUnderstand = 1; + else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:actor")) + { if ((!soap->actor || strcmp(soap->actor, tp->value)) + && strcmp(tp->value, "http://schemas.xmlsoap.org/soap/actor/next")) + soap->other = 1; + } + } + else if (soap->version == 2) + { if (!strcmp(tp->name, "ref") + || !soap_match_tag(soap, tp->name, "SOAP-ENC:ref")) + { *soap->href = '#'; + strncpy(soap->href + 1, tp->value, sizeof(soap->href) - 2); + soap->href[sizeof(soap->href)-1] = '\0'; + } + else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:itemType")) + strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1); + else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:arraySize")) + strncpy(soap->arraySize, tp->value, sizeof(soap->arraySize) - 1); + else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand") + && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true"))) + soap->mustUnderstand = 1; + else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:role")) + { if ((!soap->actor || strcmp(soap->actor, tp->value)) + && strcmp(tp->value, "http://www.w3.org/2003/05/soap-envelope/role/next")) + soap->other = 1; + } + } + } + } + return soap->error = SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_retry(struct soap *soap) +{ soap->error = SOAP_OK; + soap_revert(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_revert(struct soap *soap) +{ if (!soap->peeked) + { soap->peeked = 1; + if (soap->body) + soap->level--; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reverting last element (level=%u)\n", soap->level)); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_string_out(struct soap *soap, const char *s, int flag) +{ register const char *t; + register soap_wchar c; + register soap_wchar mask = 0xFFFFFF80UL; +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { soap->dom->data = soap_strdup(soap, s); + return SOAP_OK; + } +#endif + if (soap->mode & SOAP_C_UTFSTRING) + mask = 0; + t = s; + while ((c = *t++)) + { switch (c) + { + case 0x09: + if (flag) + { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, " ", 5)) + return soap->error; + s = t; + } + break; + case 0x0A: + if (flag || !(soap->mode & SOAP_XML_CANONICAL)) + { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, " ", 5)) + return soap->error; + s = t; + } + break; + case 0x0D: + if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, " ", 5)) + return soap->error; + s = t; + break; + case '&': + if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&", 5)) + return soap->error; + s = t; + break; + case '<': + if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "<", 4)) + return soap->error; + s = t; + break; + case '>': + if (!flag) + { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, ">", 4)) + return soap->error; + s = t; + } + break; + case '"': + if (flag) + { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, """, 6)) + return soap->error; + s = t; + } + break; + default: +#ifndef WITH_LEANER +#ifdef HAVE_MBTOWC + if (soap->mode & SOAP_C_MBSTRING) + { wchar_t wc; + register int m = mbtowc(&wc, t - 1, MB_CUR_MAX); + if (m > 0 && wc != c) + { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, wc)) + return soap->error; + s = t += m - 1; + continue; + } + } +#endif +#endif + if ((c & mask) || !(c & 0xFFFFFFE0UL)) + { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned char)c)) + return soap->error; + s = t; + } + } + } + return soap_send_raw(soap, s, t - s - 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_string_in(struct soap *soap, int flag, long minlen, long maxlen) +{ register char *s; + char *t = NULL; + register size_t i; + register long l = 0; + register int n = 0; + register int m = 0; + register soap_wchar c; +#if !defined(WITH_LEANER) && defined(HAVE_WCTOMB) + char buf[MB_LEN_MAX > 8 ? MB_LEN_MAX : 8]; +#else + char buf[8]; +#endif + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading string content\n")); + if (soap->peeked) + { if (!soap->body) + return NULL; + if (*soap->tag) + { n = 1; + soap->peeked = 0; +#ifndef WITH_LEAN + t = soap->tmpbuf; + t[0] = '<'; + strncpy(t + 1, soap->tag, sizeof(soap->tmpbuf) - 1); + strncat(t, ">", sizeof(soap->tmpbuf)); + m = strlen(soap->tag) + 2; +#endif + } + } +#ifdef WITH_CDATA + if (!flag) + { register int state = 0; +#ifdef WITH_FAST + soap->labidx = 0; /* use look-aside buffer */ +#else + if (soap_new_block(soap)) + return NULL; +#endif + for (;;) + { +#ifdef WITH_FAST + register size_t k; + if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */ + return NULL; + s = soap->labbuf + soap->labidx; /* space to populate */ + k = soap->lablen - soap->labidx; /* number of bytes available */ + soap->labidx = soap->lablen; /* claim this space */ +#else + register size_t k = SOAP_BLKLEN; + if (!(s = (char*)soap_push_block(soap, k))) + return NULL; +#endif + for (i = 0; i < k; i++) + { if (m > 0) + { *s++ = *t++; /* copy multibyte characters */ + m--; + continue; + } + c = soap_getchar(soap); + if ((int)c == EOF) + goto end; + if (c >= 0x80 && !(soap->mode & SOAP_ENC_LATIN)) + { soap_unget(soap, c); + c = soap_getutf8(soap); + if (soap->mode & SOAP_C_UTFSTRING) + { if ((c & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP) + { c &= 0x7FFFFFFF; + t = buf; + if (c < 0x0800) + *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); + else + { if (c < 0x010000) + *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + else + { if (c < 0x200000) + *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + else + { if (c < 0x04000000) + *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + else + { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + } + *t++ = (char)(0x80 | (c & 0x3F)); + m = (int)(t - buf) - 1; + t = buf; + *s++ = *t++; + continue; + } + } + } + switch (state) + { case 1: + if (c == ']') + state = 4; + *s++ = c; + continue; + case 2: + if (c == '-') + state = 6; + *s++ = c; + continue; + case 3: + if (c == '?') + state = 8; + *s++ = c; + continue; + /* CDATA */ + case 4: + if (c == ']') + state = 5; + else + state = 1; + *s++ = c; + continue; + case 5: + if (c == '>') + state = 0; + else + state = 1; + *s++ = c; + continue; + /* comment */ + case 6: + if (c == '-') + state = 7; + else + state = 2; + *s++ = c; + continue; + case 7: + if (c == '>') + state = 0; + else + state = 2; + *s++ = c; + continue; + /* PI */ + case 8: + if (c == '>') + state = 0; + else + state = 3; + *s++ = c; + continue; + } + switch (c) + { + case '/': + if (n > 0) + { c = soap_getchar(soap); + if (c == '>') + n--; + soap_unget(soap, c); + } + *s++ = '/'; + break; + case '<': + c = soap_getchar(soap); + if (c == '/') + { if (n == 0) + { c = SOAP_TT; + goto end; + } + n--; + } + else if (c == '!') + { c = soap_getchar(soap); + if (c == '[') + { do c = soap_getchar(soap); + while ((int)c != EOF && c != '['); + if ((int)c == EOF) + goto end; + t = (char*)"![CDATA["; + m = 8; + state = 1; + } + else if (c == '-') + { if ((c = soap_getchar(soap)) == '-') + state = 2; + t = (char*)"!-"; + m = 2; + soap_unget(soap, c); + } + else + { t = (char*)"!"; + m = 1; + soap_unget(soap, c); + } + *s++ = '<'; + break; + } + else if (c == '?') + state = 3; + else + n++; + soap_unget(soap, c); + *s++ = '<'; + break; + case '>': + *s++ = '>'; + break; + case '"': + *s++ = '"'; + break; + default: +#ifndef WITH_LEANER +#ifdef HAVE_WCTOMB + if (soap->mode & SOAP_C_MBSTRING) + { m = wctomb(buf, c & 0x7FFFFFFF); + if (m >= 1 && m <= (int)MB_CUR_MAX) + { t = buf; + *s++ = *t++; + m--; + } + else + { *s++ = SOAP_UNKNOWN_CHAR; + m = 0; + } + } + else +#endif +#endif + *s++ = (char)(c & 0xFF); + } + l++; + if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); + soap->error = SOAP_LENGTH; + return NULL; + } + } + } + } +#endif +#ifdef WITH_FAST + soap->labidx = 0; /* use look-aside buffer */ +#else + if (soap_new_block(soap)) + return NULL; +#endif + for (;;) + { +#ifdef WITH_FAST + register size_t k; + if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */ + return NULL; + s = soap->labbuf + soap->labidx; /* space to populate */ + k = soap->lablen - soap->labidx; /* number of bytes available */ + soap->labidx = soap->lablen; /* claim this space */ +#else + register size_t k = SOAP_BLKLEN; + if (!(s = (char*)soap_push_block(soap, k))) + return NULL; +#endif + for (i = 0; i < k; i++) + { if (m > 0) + { *s++ = *t++; /* copy multibyte characters */ + m--; + continue; + } + if (soap->mode & SOAP_C_UTFSTRING) + { if (((c = soap_get(soap)) & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP) + { c &= 0x7FFFFFFF; + t = buf; + if (c < 0x0800) + *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); + else + { if (c < 0x010000) + *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + else + { if (c < 0x200000) + *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + else + { if (c < 0x04000000) + *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + else + { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + } + *t++ = (char)(0x80 | (c & 0x3F)); + m = (int)(t - buf) - 1; + t = buf; + *s++ = *t++; + continue; + } + } + else + c = soap_getutf8(soap); + switch (c) + { + case SOAP_TT: + if (n == 0) + goto end; + n--; + *s++ = '<'; + t = (char*)"/"; + m = 1; + break; + case SOAP_LT: + n++; + *s++ = '<'; + break; + case SOAP_GT: + *s++ = '>'; + break; + case SOAP_QT: + *s++ = '"'; + break; + case SOAP_AP: + *s++ = '\''; + break; + case '/': + if (n > 0) + { c = soap_get(soap); + if (c == SOAP_GT) + n--; + soap_unget(soap, c); + } + *s++ = '/'; + break; + case '<' | 0x80000000: + if (flag) + *s++ = '<'; + else + { *s++ = '&'; + t = (char*)"lt;"; + m = 3; + } + break; + case '>' | 0x80000000: + if (flag) + *s++ = '>'; + else + { *s++ = '&'; + t = (char*)"gt;"; + m = 3; + } + break; + case '&' | 0x80000000: + if (flag) + *s++ = '&'; + else + { *s++ = '&'; + t = (char*)"amp;"; + m = 4; + } + break; + case '"' | 0x80000000: + if (flag) + *s++ = '"'; + else + { *s++ = '&'; + t = (char*)"quot;"; + m = 5; + } + break; + case '\'' | 0x80000000: + if (flag) + *s++ = '\''; + else + { *s++ = '&'; + t = (char*)"apos;"; + m = 5; + } + break; + default: + if ((int)c == EOF) + goto end; +#ifndef WITH_LEANER +#ifdef HAVE_WCTOMB + if (soap->mode & SOAP_C_MBSTRING) + { m = wctomb(buf, c & 0x7FFFFFFF); + if (m >= 1 && m <= (int)MB_CUR_MAX) + { t = buf; + *s++ = *t++; + m--; + } + else + { *s++ = SOAP_UNKNOWN_CHAR; + m = 0; + } + } + else +#endif +#endif + *s++ = (char)(c & 0xFF); + } + l++; + if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); + soap->error = SOAP_LENGTH; + return NULL; + } + } + } +end: + soap_unget(soap, c); + *s = '\0'; +#ifdef WITH_FAST + t = soap_strdup(soap, soap->labbuf); +#else + soap_size_block(soap, i+1); + t = soap_save_block(soap, NULL, 0); +#endif + if ((soap->mode & SOAP_XML_STRICT) && l < minlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen)); + soap->error = SOAP_LENGTH; + return NULL; + } +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { if (flag == 3) + soap->dom->tail = t; + else + soap->dom->data = t; + } +#endif + if (flag == 2) + if (soap_s2QName(soap, t, &t)) + return NULL; + return t; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_wstring_out(struct soap *soap, const wchar_t *s, int flag) +{ const char *t; + char tmp; + register soap_wchar c; +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { wchar_t *r = (wchar_t*)s; + int n = 1; + while (*r++) + n++; + soap->dom->wide = r = (wchar_t*)soap_malloc(soap, n * sizeof(wchar_t)); + while (n--) + *r++ = *s++; + return SOAP_OK; + } +#endif + while ((c = *s++)) + { switch (c) + { + case 0x09: + if (flag) + t = " "; + else + t = "\t"; + break; + case 0x0A: + if (flag || !(soap->mode & SOAP_XML_CANONICAL)) + t = " "; + else + t = "\n"; + break; + case 0x0D: + t = " "; + break; + case '&': + t = "&"; + break; + case '<': + t = "<"; + break; + case '>': + if (flag) + t = ">"; + else + t = ">"; + break; + case '"': + if (flag) + t = """; + else + t = "\""; + break; + default: + if (c >= 0x20 && c < 0x80) + { tmp = (char)c; + if (soap_send_raw(soap, &tmp, 1)) + return soap->error; + } + else if (soap_pututf8(soap, (unsigned long)c)) + return soap->error; + continue; + } + if (soap_send(soap, t)) + return soap->error; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +wchar_t * +SOAP_FMAC2 +soap_wstring_in(struct soap *soap, int flag, long minlen, long maxlen) +{ wchar_t *s; + register int i, n = 0; + register long l = 0; + register soap_wchar c; + const char *t = NULL; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading wide string content\n")); + if (soap->peeked) + { if (!soap->body) + return NULL; + if (*soap->tag) + { n = 1; + soap->peeked = 0; + } + } + if (soap_new_block(soap)) + return NULL; + for (;;) + { if (!(s = (wchar_t*)soap_push_block(soap, sizeof(wchar_t)*SOAP_BLKLEN))) + return NULL; + for (i = 0; i < SOAP_BLKLEN; i++) + { if (t) + { *s++ = (wchar_t)*t++; + if (!*t) + t = NULL; + continue; + } + c = soap_getutf8(soap); + switch (c) + { + case SOAP_TT: + if (n == 0) + goto end; + n--; + *s++ = '<'; + soap_unget(soap, '/'); + break; + case SOAP_LT: + n++; + *s++ = '<'; + break; + case SOAP_GT: + *s++ = '>'; + break; + case SOAP_QT: + *s++ = '"'; + break; + case SOAP_AP: + *s++ = '\''; + break; + case '/': + if (n > 0) + { c = soap_getutf8(soap); + if (c == SOAP_GT) + n--; + soap_unget(soap, c); + } + *s++ = '/'; + break; + case '<': + if (flag) + *s++ = (soap_wchar)'<'; + else + { *s++ = (soap_wchar)'&'; + t = "lt;"; + } + break; + case '>': + if (flag) + *s++ = (soap_wchar)'>'; + else + { *s++ = (soap_wchar)'&'; + t = "gt;"; + } + break; + case '"': + if (flag) + *s++ = (soap_wchar)'"'; + else + { *s++ = (soap_wchar)'&'; + t = "quot;"; + } + break; + default: + if ((int)c == EOF) + goto end; + *s++ = (wchar_t)c & 0x7FFFFFFF; + } + l++; + if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); + soap->error = SOAP_LENGTH; + return NULL; + } + } + } +end: + soap_unget(soap, c); + *s = '\0'; + soap_size_block(soap, sizeof(wchar_t) * (i + 1)); + if ((soap->mode & SOAP_XML_STRICT) && l < minlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen)); + soap->error = SOAP_LENGTH; + return NULL; + } + s = (wchar_t*)soap_save_block(soap, NULL, 0); +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + soap->dom->wide = s; +#endif + return s; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_int2s(struct soap *soap, int n) +{ return soap_long2s(soap, (long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outint(struct soap *soap, const char *tag, int id, const int *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_long2s(soap, (long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2int(struct soap *soap, const char *s, int *p) +{ if (s) + { char *r; +#ifndef WITH_NOIO +#ifndef WITH_LEAN + soap_reset_errno; +#endif +#endif + *p = (int)soap_strtol(s, &r, 10); + if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r +#ifndef WITH_NOIO +#ifndef WITH_LEAN + || soap_errno == SOAP_ERANGE +#endif +#endif + ) + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int * +SOAP_FMAC2 +soap_inint(struct soap *soap, const char *tag, int *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":int") + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (int*)soap_id_enter(soap, soap->id, p, t, sizeof(int), 0, NULL, NULL, NULL); + if (*soap->href) + p = (int*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(int), 0, NULL); + else if (p) + { if (soap_s2int(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_long2s(struct soap *soap, long n) +{ sprintf(soap->tmpbuf, "%ld", n); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outlong(struct soap *soap, const char *tag, int id, const long *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_long2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2long(struct soap *soap, const char *s, long *p) +{ if (s) + { char *r; +#ifndef WITH_NOIO +#ifndef WITH_LEAN + soap_reset_errno; +#endif +#endif + *p = soap_strtol(s, &r, 10); + if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r +#ifndef WITH_NOIO +#ifndef WITH_LEAN + || soap_errno == SOAP_ERANGE +#endif +#endif + ) + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +long * +SOAP_FMAC2 +soap_inlong(struct soap *soap, const char *tag, long *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":int") + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (long*)soap_id_enter(soap, soap->id, p, t, sizeof(long), 0, NULL, NULL, NULL); + if (*soap->href) + p = (long*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(long), 0, NULL); + else if (p) + { if (soap_s2long(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_LONG642s(struct soap *soap, LONG64 n) +{ sprintf(soap->tmpbuf, SOAP_LONG_FORMAT, n); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outLONG64(struct soap *soap, const char *tag, int id, const LONG64 *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_LONG642s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2LONG64(struct soap *soap, const char *s, LONG64 *p) +{ if (s) + { +#ifdef HAVE_STRTOLL + char *r; +#ifndef WITH_NOIO +#ifndef WITH_LEAN + soap_reset_errno; +#endif +#endif + *p = strtoll(s, &r, 10); + if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r +#ifndef WITH_NOIO +#ifndef WITH_LEAN + || soap_errno == SOAP_ERANGE +#endif +#endif + ) +#else +# ifdef HAVE_SSCANF + if (sscanf(s, SOAP_LONG_FORMAT, p) != 1) +# endif +#endif + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +LONG64 * +SOAP_FMAC2 +soap_inLONG64(struct soap *soap, const char *tag, LONG64 *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":integer") + && soap_match_tag(soap, soap->type, ":positiveInteger") + && soap_match_tag(soap, soap->type, ":negativeInteger") + && soap_match_tag(soap, soap->type, ":nonPositiveInteger") + && soap_match_tag(soap, soap->type, ":nonNegativeInteger") + && soap_match_tag(soap, soap->type, ":long") + && soap_match_tag(soap, soap->type, ":int") + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (LONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(LONG64), 0, NULL, NULL, NULL); + if (*soap->href) + p = (LONG64*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(LONG64), 0, NULL); + else if (p) + { if (soap_s2LONG64(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_byte2s(struct soap *soap, char n) +{ return soap_long2s(soap, (long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outbyte(struct soap *soap, const char *tag, int id, const char *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_long2s(soap, (long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2byte(struct soap *soap, const char *s, char *p) +{ if (s) + { long n; + char *r; + n = soap_strtol(s, &r, 10); + if (s == r || *r || n < -128 || n > 127) + soap->error = SOAP_TYPE; + *p = (char)n; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_inbyte(struct soap *soap, const char *tag, char *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (char*)soap_id_enter(soap, soap->id, p, t, sizeof(char), 0, NULL, NULL, NULL); + if (*soap->href) + p = (char*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(char), 0, NULL); + else if (p) + { if (soap_s2byte(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_short2s(struct soap *soap, short n) +{ return soap_long2s(soap, (long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outshort(struct soap *soap, const char *tag, int id, const short *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_long2s(soap, (long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2short(struct soap *soap, const char *s, short *p) +{ if (s) + { long n; + char *r; + n = soap_strtol(s, &r, 10); + if (s == r || *r || n < -32768 || n > 32767) + soap->error = SOAP_TYPE; + *p = (short)n; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +short * +SOAP_FMAC2 +soap_inshort(struct soap *soap, const char *tag, short *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (short*)soap_id_enter(soap, soap->id, p, t, sizeof(short), 0, NULL, NULL, NULL); + if (*soap->href) + p = (short*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(short), 0, NULL); + else if (p) + { if (soap_s2short(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_float2s(struct soap *soap, float n) +{ char *s, *t; + if (soap_isnan((double)n)) + return "NaN"; + if (soap_ispinff(n)) + return "INF"; + if (soap_isninff(n)) + return "-INF"; + s = soap->tmpbuf; + sprintf(soap->tmpbuf, soap->float_format, n); + t = strchr(s, ','); /* convert decimal comma to DP */ + if (t) + *t = '.'; + return s; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outfloat(struct soap *soap, const char *tag, int id, const float *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_float2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2float(struct soap *soap, const char *s, float *p) +{ if (s) + { if (!*s) + return soap->error = SOAP_TYPE; + if (!soap_tag_cmp(s, "INF")) + *p = FLT_PINFTY; + else if (!soap_tag_cmp(s, "+INF")) + *p = FLT_PINFTY; + else if (!soap_tag_cmp(s, "-INF")) + *p = FLT_NINFTY; + else if (!soap_tag_cmp(s, "NaN")) + *p = FLT_NAN; + else + { +/* On some systems, strtof appears to be broken or doesn't link: use with caution */ +#if defined(HAVE_STRTOF) + char *r; + *p = strtof((char*)s, &r); + if (*r) +#elif defined(HAVE_STRTOD) + char *r; + *p = (float)strtod(s, &r); + if (*r) +#endif +#ifdef HAVE_SSCANF + if (sscanf(s, "%g", p) != 1) + soap->error = SOAP_TYPE; +#else + soap->error = SOAP_TYPE; +#endif + } + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static int soap_isnumeric(struct soap *soap, const char *type) +{ if (soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":float") + && soap_match_tag(soap, soap->type, ":double") + && soap_match_tag(soap, soap->type, ":decimal") + && soap_match_tag(soap, soap->type, ":integer") + && soap_match_tag(soap, soap->type, ":positiveInteger") + && soap_match_tag(soap, soap->type, ":negativeInteger") + && soap_match_tag(soap, soap->type, ":nonPositiveInteger") + && soap_match_tag(soap, soap->type, ":nonNegativeInteger") + && soap_match_tag(soap, soap->type, ":long") + && soap_match_tag(soap, soap->type, ":int") + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte") + && soap_match_tag(soap, soap->type, ":unsignedLong") + && soap_match_tag(soap, soap->type, ":unsignedInt") + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return SOAP_ERR; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +float * +SOAP_FMAC2 +soap_infloat(struct soap *soap, const char *tag, float *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type != '\0' && soap_isnumeric(soap, type)) + return NULL; +#endif + p = (float*)soap_id_enter(soap, soap->id, p, t, sizeof(float), 0, NULL, NULL, NULL); + if (*soap->href) + p = (float*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(float), 0, NULL); + else if (p) + { if (soap_s2float(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_double2s(struct soap *soap, double n) +{ char *s, *t; + if (soap_isnan(n)) + return "NaN"; + if (soap_ispinfd(n)) + return "INF"; + if (soap_isninfd(n)) + return "-INF"; + s = soap->tmpbuf; + sprintf(soap->tmpbuf, soap->double_format, n); + t = strchr(s, ','); /* convert decimal comma to DP */ + if (t) + *t = '.'; + return s; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outdouble(struct soap *soap, const char *tag, int id, const double *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_double2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2double(struct soap *soap, const char *s, double *p) +{ if (s) + { if (!*s) + return soap->error = SOAP_TYPE; + if (!soap_tag_cmp(s, "INF")) + *p = DBL_PINFTY; + else if (!soap_tag_cmp(s, "+INF")) + *p = DBL_PINFTY; + else if (!soap_tag_cmp(s, "-INF")) + *p = DBL_NINFTY; + else if (!soap_tag_cmp(s, "NaN")) + *p = DBL_NAN; + else + { +#ifdef HAVE_STRTOD + char *r; + *p = strtod(s, &r); + if (*r) +#endif +#ifdef HAVE_SSCANF + if (sscanf(s, "%lg", p) != 1) + soap->error = SOAP_TYPE; +#else + soap->error = SOAP_TYPE; +#endif + } + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +double * +SOAP_FMAC2 +soap_indouble(struct soap *soap, const char *tag, double *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type != '\0' && soap_isnumeric(soap, type)) + return NULL; +#endif + p = (double*)soap_id_enter(soap, soap->id, p, t, sizeof(double), 0, NULL, NULL, NULL); + if (*soap->href) + p = (double*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(double), 0, NULL); + else if (p) + { if (soap_s2double(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_unsignedByte2s(struct soap *soap, unsigned char n) +{ return soap_unsignedLong2s(soap, (unsigned long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outunsignedByte(struct soap *soap, const char *tag, int id, const unsigned char *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2unsignedByte(struct soap *soap, const char *s, unsigned char *p) +{ if (s) + { unsigned long n; + char *r; + n = soap_strtoul(s, &r, 10); + if (s == r || *r || n > 255) + soap->error = SOAP_TYPE; + *p = (unsigned char)n; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +unsigned char * +SOAP_FMAC2 +soap_inunsignedByte(struct soap *soap, const char *tag, unsigned char *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (unsigned char*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned char), 0, NULL, NULL, NULL); + if (*soap->href) + p = (unsigned char*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned char), 0, NULL); + else if (p) + { if (soap_s2unsignedByte(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_unsignedShort2s(struct soap *soap, unsigned short n) +{ return soap_unsignedLong2s(soap, (unsigned long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outunsignedShort(struct soap *soap, const char *tag, int id, const unsigned short *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2unsignedShort(struct soap *soap, const char *s, unsigned short *p) +{ if (s) + { unsigned long n; + char *r; + n = soap_strtoul(s, &r, 10); + if (s == r || *r || n > 65535) + soap->error = SOAP_TYPE; + *p = (unsigned short)n; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +unsigned short * +SOAP_FMAC2 +soap_inunsignedShort(struct soap *soap, const char *tag, unsigned short *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (unsigned short*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned short), 0, NULL, NULL, NULL); + if (*soap->href) + p = (unsigned short*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned short), 0, NULL); + else if (p) + { if (soap_s2unsignedShort(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_unsignedInt2s(struct soap *soap, unsigned int n) +{ return soap_unsignedLong2s(soap, (unsigned long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outunsignedInt(struct soap *soap, const char *tag, int id, const unsigned int *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2unsignedInt(struct soap *soap, const char *s, unsigned int *p) +{ if (s) + { char *r; +#ifndef WITH_NOIO +#ifndef WITH_LEAN + soap_reset_errno; +#endif +#endif + *p = (unsigned int)soap_strtoul(s, &r, 10); + if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r +#ifndef WITH_NOIO +#ifndef WITH_LEAN + || soap_errno == SOAP_ERANGE +#endif +#endif + ) + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +unsigned int * +SOAP_FMAC2 +soap_inunsignedInt(struct soap *soap, const char *tag, unsigned int *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":unsignedInt") + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (unsigned int*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned int), 0, NULL, NULL, NULL); + if (*soap->href) + p = (unsigned int*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned int), 0, NULL); + else if (p) + { if (soap_s2unsignedInt(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_unsignedLong2s(struct soap *soap, unsigned long n) +{ sprintf(soap->tmpbuf, "%lu", n); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outunsignedLong(struct soap *soap, const char *tag, int id, const unsigned long *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_unsignedLong2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2unsignedLong(struct soap *soap, const char *s, unsigned long *p) +{ if (s) + { char *r; +#ifndef WITH_NOIO +#ifndef WITH_LEAN + soap_reset_errno; +#endif +#endif + *p = soap_strtoul(s, &r, 10); + if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r +#ifndef WITH_NOIO +#ifndef WITH_LEAN + || soap_errno == SOAP_ERANGE +#endif +#endif + ) + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +unsigned long * +SOAP_FMAC2 +soap_inunsignedLong(struct soap *soap, const char *tag, unsigned long *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":unsignedInt") + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (unsigned long*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned long), 0, NULL, NULL, NULL); + if (*soap->href) + p = (unsigned long*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned long), 0, NULL); + else if (p) + { if (soap_s2unsignedLong(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_ULONG642s(struct soap *soap, ULONG64 n) +{ sprintf(soap->tmpbuf, SOAP_ULONG_FORMAT, n); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outULONG64(struct soap *soap, const char *tag, int id, const ULONG64 *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_ULONG642s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2ULONG64(struct soap *soap, const char *s, ULONG64 *p) +{ if (s) + { +#ifdef HAVE_STRTOULL + char *r; +#ifndef WITH_NOIO +#ifndef WITH_LEAN + soap_reset_errno; +#endif +#endif + *p = strtoull(s, &r, 10); + if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r +#ifndef WITH_NOIO +#ifndef WITH_LEAN + || soap_errno == SOAP_ERANGE +#endif +#endif + ) +#else +# ifdef HAVE_SSCANF + if (sscanf(s, SOAP_ULONG_FORMAT, p) != 1) +# endif +#endif + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +ULONG64 * +SOAP_FMAC2 +soap_inULONG64(struct soap *soap, const char *tag, ULONG64 *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":positiveInteger") + && soap_match_tag(soap, soap->type, ":nonNegativeInteger") + && soap_match_tag(soap, soap->type, ":unsignedLong") + && soap_match_tag(soap, soap->type, ":unsignedInt") + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } + p = (ULONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(ULONG64), 0, NULL, NULL, NULL); + if (*soap->href) + p = (ULONG64*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(ULONG64), 0, NULL); + else if (p) + { if (soap_s2ULONG64(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2string(struct soap *soap, const char *s, char **t) +{ *t = NULL; + if (s) + { if (!(*t = soap_strdup(soap, s))) + return soap->error = SOAP_EOM; + if (!(soap->mode & (SOAP_ENC_LATIN | SOAP_C_UTFSTRING))) + { /* TODO: consider truncating UTF8 to ASCII for regular XML attribute strings? */ + } + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2QName(struct soap *soap, const char *s, char **t) +{ if (s) + { struct soap_nlist *np = soap->nlist; + const char *p; + /* if there is no namespace stack, or prefix is "xml" then pass string */ + if (!np || !strncmp(s, "xml:", 4)) + { *t = soap_strdup(soap, s); + return SOAP_OK; + } + /* else we normalize the QName by replacing its prefix */ + p = strchr(s, ':'); + if (p) + { register int n = p - s; + while (np && (strncmp(np->id, s, n) || np->id[n])) + np = np->next; + p++; + } + else + { while (np && *np->id) + np = np->next; + p = s; + } + if (np) + { if (np->index >= 0 && soap->local_namespaces) + { register const char *q = soap->local_namespaces[np->index].id; + if (q) + { if ((*t = (char*)soap_malloc(soap, strlen(p) + strlen(q) + 2))) + sprintf(*t, "%s:%s", q, p); + return SOAP_OK; + } + } + if (np->ns) + { if ((*t = (char*)soap_malloc(soap, strlen(p) + strlen(np->ns) + 4))) + sprintf(*t, "\"%s\":%s", np->ns, p); + return SOAP_OK; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Namespace prefix of '%s' not defined (index=%d, URI=%s)\n", s, np->index, np->ns?np->ns:"")); + return soap->error = SOAP_NAMESPACE; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Namespace prefix of '%s' not defined, assuming empty namespace\n", s)); + if ((*t = (char*)soap_malloc(soap, strlen(p) + 4))) + sprintf(*t, "\"\":%s", p); + } + else + *t = NULL; + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_QName2s(struct soap *soap, const char *s) +{ struct Namespace *p; + char *t; + int n; + if (!s || *s != '"') + { +#ifndef WITH_LEAN + if (s && (soap->mode & SOAP_XML_CANONICAL)) + { t = (char*)strchr(s, ':'); + if (t) + soap_utilize_ns(soap, s, t - s); + } +#endif + return s; + } + s++; + if ((p = soap->local_namespaces)) + { for (; p->id; p++) + { if (p->ns) + if (!soap_tag_cmp(s, p->ns)) + break; + if (p->in) + if (!soap_tag_cmp(s, p->in)) + break; + } + if (p && p->id) + { s = strchr(s, '"'); + if (s) + { t = (char*)soap_malloc(soap, strlen(p->id) + strlen(s)); + strcpy(t, p->id); + strcat(t, s + 1); + return t; + } + } + } + t = (char*)strchr(s, '"'); + if (t) + n = t - s; + else + n = 0; + t = soap_strdup(soap, s); + t[n] = '\0'; + sprintf(soap->tmpbuf, "xmlns:_%d", soap->idnum++); + soap_set_attr(soap, soap->tmpbuf, t); + s = strchr(s, '"'); + if (s) + { t = (char*)soap_malloc(soap, strlen(soap->tmpbuf) + strlen(s) - 6); + strcpy(t, soap->tmpbuf + 6); + strcat(t, s + 1); + } + return t; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2wchar(struct soap *soap, const char *s, wchar_t **t) +{ wchar_t *r; + if (!s) + *t = NULL; + else + { *t = r = (wchar_t*)soap_malloc(soap, sizeof(wchar_t) * (strlen(s) + 1)); + if (!r) + return soap->error; + if (soap->mode & SOAP_ENC_LATIN) + { while (*s) + *r++ = (wchar_t)*s++; + } + else + { /* Convert UTF8 to wchar */ + while (*s) + { register soap_wchar c, c1, c2, c3, c4; + c = *s++; + if (c < 0x80) + *r++ = (wchar_t)c; + else + { c1 = (soap_wchar)*s++ & 0x3F; + if (c < 0xE0) + *r++ = (wchar_t)(((soap_wchar)(c & 0x1F) << 6) | c1); + else + { c2 = (soap_wchar)*s++ & 0x3F; + if (c < 0xF0) + *r++ = (wchar_t)(((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2); + else + { c3 = (soap_wchar)*s++ & 0x3F; + if (c < 0xF8) + *r++ = (wchar_t)(((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3); + else + { c4 = (soap_wchar)*s++ & 0x3F; + if (c < 0xFC) + *r++ = (wchar_t)(((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4); + else + *r++ = (wchar_t)(((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(*s++ & 0x3F)); + } + } + } + } + } + } + *r = L'\0'; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_wchar2s(struct soap *soap, const wchar_t *s) +{ register soap_wchar c; + register char *r, *t; + const wchar_t *q = s; + size_t n = 0; + while ((c = *q++)) + { if (c > 0 && c < 0x80) + n++; + else + n += 6; + } + r = t = (char*)soap_malloc(soap, n + 1); + if (r) + { /* Convert wchar to UTF8 */ + while ((c = *s++)) + { if (c > 0 && c < 0x80) + *t++ = (char)c; + else + { if (c < 0x0800) + *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); + else + { if (c < 0x010000) + *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + else + { if (c < 0x200000) + *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + else + { if (c < 0x04000000) + *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + else + { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + } + *t++ = (char)(0x80 | (c & 0x3F)); + } + } + *t = '\0'; + } + return r; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outstring(struct soap *soap, const char *tag, int id, char *const*p, const char *type, int n) +{ id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n); + if (id < 0) + return soap->error; + if (!**p && (soap->mode & SOAP_C_NILSTRING)) + return soap_element_null(soap, tag, id, type); + if (soap_element_begin_out(soap, tag, id, type) + || soap_string_out(soap, *p, 0) + || soap_element_end_out(soap, tag)) + return soap->error; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char ** +SOAP_FMAC2 +soap_instring(struct soap *soap, const char *tag, char **p, const char *type, int t, int flag, long minlen, long maxlen) +{ if (soap_element_begin_in(soap, tag, 1, NULL)) + { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG) + return NULL; + soap->error = SOAP_OK; + } + if (!p) + { if (!(p = (char**)soap_malloc(soap, sizeof(char*)))) + return NULL; + } + if (soap->body) + { *p = soap_string_in(soap, flag, minlen, maxlen); + if (!*p || !(char*)soap_id_enter(soap, soap->id, *p, t, sizeof(char*), 0, NULL, NULL, NULL)) + return NULL; + if (!**p && (!tag || *tag == '-')) + { soap->error = SOAP_NO_TAG; + return NULL; + } + } + else if (soap->null) + *p = NULL; + else + *p = (char*)SOAP_STR_EOS; + if (*soap->href) + p = (char**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(char**), 0); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outwstring(struct soap *soap, const char *tag, int id, wchar_t *const*p, const char *type, int n) +{ id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n); + if (id < 0) + return soap->error; + if (!**p && (soap->mode & SOAP_C_NILSTRING)) + return soap_element_null(soap, tag, id, type); + if (soap_element_begin_out(soap, tag, id, type) + || soap_wstring_out(soap, *p, 0) + || soap_element_end_out(soap, tag)) + return soap->error; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +wchar_t ** +SOAP_FMAC2 +soap_inwstring(struct soap *soap, const char *tag, wchar_t **p, const char *type, int t, long minlen, long maxlen) +{ if (soap_element_begin_in(soap, tag, 1, NULL)) + { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG) + return NULL; + soap->error = SOAP_OK; + } + if (!p) + { if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*)))) + return NULL; + } + if (soap->body) + { *p = soap_wstring_in(soap, 1, minlen, maxlen); + if (!*p || !(wchar_t*)soap_id_enter(soap, soap->id, *p, t, sizeof(wchar_t*), 0, NULL, NULL, NULL)) + return NULL; + if (!**p && (!tag || *tag == '-')) + { soap->error = SOAP_NO_TAG; + return NULL; + } + } + else if (soap->null) + *p = NULL; + else + *p = (wchar_t*)SOAP_STR_EOS; + if (*soap->href) + p = (wchar_t**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(wchar_t**), 0); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static time_t +soap_timegm(struct tm *T) +{ +#if defined(HAVE_TIMEGM) + return timegm(T); +#else + time_t t, g, z; +#ifdef HAVE_GMTIME_R + struct tm tm, *tmp = &tm; +#else + struct tm *tmp; +#endif + t = mktime(T); + if (t == -1) + return -1; +#ifdef HAVE_GMTIME_R + gmtime_r(&t, tmp); +#else + tmp = gmtime(&t); +#endif + tmp->tm_isdst = 0; + g = mktime(tmp); + if (g == -1) + return -1; + z = g - t; + return t - z; +#endif +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_dateTime2s(struct soap *soap, time_t n) +{ struct tm T, *pT = &T; +#if defined(HAVE_GMTIME_R) + if (gmtime_r(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); + /* The following defines were added for VxWorks*/ +#elif defined(HAVE_PGMTIME_R) + if (gmtime_r(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); +#elif defined(HAVE_PGMTIME) + if (gmtime(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); +#elif defined(HAVE_GMTIME) + if ((pT = gmtime(&n))) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); +#elif defined(HAVE_GETTIMEOFDAY) + struct timezone tz; + memset((void*)&tz, 0, sizeof(tz)); +# if defined(HAVE_LOCALTIME_R) + if (localtime_r(&n, pT)) + { struct timeval tv; + gettimeofday(&tv, &tz); + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60); + } +# else + if ((pT = localtime(&n))) + { struct timeval tv; + gettimeofday(&tv, &tz); + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60); + } +#endif +#elif defined(HAVE_FTIME) + struct timeb t; + memset((void*)&t, 0, sizeof(t)); +# if defined(HAVE_LOCALTIME_R) + if (localtime_r(&n, pT)) + { +#ifdef __BORLANDC__ + ::ftime(&t); +#else + ftime(&t); +#endif + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60); + } + /* The following defines were added for VxWorks*/ +# elif defined(HAVE_PLOCALTIME_R) + if (localtime_r(&n, pT)) + { strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf+strlen(soap->tmpbuf), "%+03d:%02d", t.timezone/60, abs(t.timezone)%60); + } +# else + if ((pT = localtime(&n))) + { +#ifdef __BORLANDC__ + ::ftime(&t); +#else + ftime(&t); +#endif + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60); + } +# endif +#elif defined(HAVE_LOCALTIME_R) + if (localtime_r(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + /* The following defines were added for VxWorks*/ +#elif defined(HAVE_PLOCALTIME_R) + if (localtime_r(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); +#else + if ((pT = localtime(&n))) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); +#endif + else + strcpy(soap->tmpbuf, "1969-12-31T23:59:59Z"); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outdateTime(struct soap *soap, const char *tag, int id, const time_t *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_dateTime2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2dateTime(struct soap *soap, const char *s, time_t *p) +{ if (s) + { struct tm T; + char zone[32]; + const char *t; + memset((void*)&T, 0, sizeof(T)); + zone[sizeof(zone)-1] = '\0'; + if (strchr(s, '-')) + t = "%d-%d-%dT%d:%d:%d%31s"; + else if (strchr(s, ':')) + t = "%4d%2d%2dT%d:%d:%d%31s"; + else /* parse non-XSD-standard alternative ISO 8601 format */ + t = "%4d%2d%2dT%2d%2d%2d%31s"; + sscanf(s, t, &T.tm_year, &T.tm_mon, &T.tm_mday, &T.tm_hour, &T.tm_min, &T.tm_sec, zone); + if (T.tm_year == 1) + T.tm_year = 70; + else + T.tm_year -= 1900; + T.tm_mon--; + if (*zone) + { if (*zone == '.') + { for (s = zone + 1; *s; s++) + if (*s < '0' || *s > '9') + break; + } + else + s = zone; + if (*s == '+' || *s == '-') + { int h = 0, m = 0; + if (s[3] == ':') + { sscanf(s, "%d:%d", &h, &m); + if (h < 0) + m = -m; + } + else + { m = (int)atol(s); + h = m / 100; + m = m % 100; + } + T.tm_hour -= h; + T.tm_min -= m; + } + T.tm_isdst = 0; + *p = soap_timegm(&T); + } + else + { T.tm_isdst = -1; + *p = mktime(&T); /* no time zone: suppose it is localtime? */ + } + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +time_t * +SOAP_FMAC2 +soap_indateTime(struct soap *soap, const char *tag, time_t *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":dateTime")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } + p = (time_t*)soap_id_enter(soap, soap->id, p, t, sizeof(time_t), 0, NULL, NULL, NULL); + if (*soap->href) + p = (time_t*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(time_t), 0, NULL); + else if (p) + { if (soap_s2dateTime(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outliteral(struct soap *soap, const char *tag, char *const*p, const char *type) +{ int i; + const char *t = NULL; + if (tag && *tag != '-') + { if (soap->local_namespaces && (t = strchr(tag, ':'))) + { strncpy(soap->tmpbuf, tag, t-tag); + soap->tmpbuf[t-tag] = '\0'; + for (i = 0; soap->local_namespaces[i].id; i++) + if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id)) + break; + t++; + if (soap_element(soap, t, 0, type) + || soap_attribute(soap, "xmlns", soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS) + || soap_element_start_end_out(soap, NULL)) + return soap->error; + } + else + { t = tag; + if (soap_element_begin_out(soap, t, 0, type)) + return soap->error; + } + } + if (p && *p) + { if (soap_send(soap, *p)) + return soap->error; + } + if (t) + return soap_element_end_out(soap, t); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char ** +SOAP_FMAC2 +soap_inliteral(struct soap *soap, const char *tag, char **p) +{ if (soap_element_begin_in(soap, tag, 1, NULL)) + { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT) + return NULL; + soap->error = SOAP_OK; + } + if (!p) + { if (!(p = (char**)soap_malloc(soap, sizeof(char*)))) + return NULL; + } + if (soap->body) + { *p = soap_string_in(soap, 0, -1, -1); + if (!*p) + return NULL; + if (!**p && (!tag || *tag == '-')) + { soap->error = SOAP_NO_TAG; + return NULL; + } + } + else if (soap->null) + *p = NULL; + else + *p = (char*)SOAP_STR_EOS; + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outwliteral(struct soap *soap, const char *tag, wchar_t *const*p, const char *type) +{ int i; + const char *t = NULL; + if (tag && *tag != '-') + { if (soap->local_namespaces && (t = strchr(tag, ':'))) + { strncpy(soap->tmpbuf, tag, t-tag); + soap->tmpbuf[t-tag] = '\0'; + for (i = 0; soap->local_namespaces[i].id; i++) + if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id)) + break; + t++; + if (soap_element(soap, t, 0, type) + || soap_attribute(soap, "xmlns", soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS) + || soap_element_start_end_out(soap, NULL)) + return soap->error; + } + else + { t = tag; + if (soap_element_begin_out(soap, t, 0, type)) + return soap->error; + } + if (soap_send(soap, soap->tmpbuf)) + return soap->error; + } + if (p) + { wchar_t c; + const wchar_t *s = *p; + while ((c = *s++)) + { if (soap_pututf8(soap, (unsigned long)c)) + return soap->error; + } + } + if (t) + return soap_element_end_out(soap, t); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +wchar_t ** +SOAP_FMAC2 +soap_inwliteral(struct soap *soap, const char *tag, wchar_t **p) +{ if (soap_element_begin_in(soap, tag, 1, NULL)) + { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT) + return NULL; + soap->error = SOAP_OK; + } + if (!p) + { if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*)))) + return NULL; + } + if (soap->body) + { *p = soap_wstring_in(soap, 0, -1, -1); + if (!*p) + return NULL; + if (!**p && (!tag || *tag == '-')) + { soap->error = SOAP_NO_TAG; + return NULL; + } + } + else if (soap->null) + *p = NULL; + else + *p = (wchar_t*)SOAP_STR_EOS; + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char * +SOAP_FMAC2 +soap_value(struct soap *soap) +{ register size_t i; + register soap_wchar c = 0; + register char *s = soap->tmpbuf; + if (!soap->body) + return SOAP_STR_EOS; + do c = soap_get(soap); + while (soap_blank(c)); + for (i = 0; i < sizeof(soap->tmpbuf) - 1; i++) + { if (c == SOAP_TT || (int)c == EOF) + break; + *s++ = (char)c; + c = soap_get(soap); + } + for (s--; i > 0; i--, s--) + { if (!soap_blank(*s)) + break; + } + s[1] = '\0'; + if ((int)c == EOF || c == SOAP_TT) + soap_unget(soap, c); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element content value='%s'\n", soap->tmpbuf)); +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + soap->dom->data = soap_strdup(soap, soap->tmpbuf); +#endif + return soap->tmpbuf; /* return non-null pointer */ +} +#endif + +/******************************************************************************/ +#if !defined(WITH_LEANER) || !defined(WITH_NOHTTP) +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getline(struct soap *soap, char *s, int len) +{ int i = len; + soap_wchar c = 0; + for (;;) + { while (--i > 0) + { c = soap_getchar(soap); + if (c == '\r' || c == '\n') + break; + if ((int)c == EOF) + return soap->error = SOAP_EOF; + *s++ = (char)c; + } + if (c != '\n') + c = soap_getchar(soap); /* got \r, now get \n */ + if (c == '\n') + { *s = '\0'; + if (i+1 == len) /* empty line: end of HTTP/MIME header */ + break; + c = soap_unget(soap, soap_getchar(soap)); + if (c != ' ' && c != '\t') /* HTTP line continuation? */ + break; + } + else if ((int)c == EOF) + return soap->error = SOAP_EOF; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static size_t +soap_count_attachments(struct soap *soap) +{ +#ifndef WITH_LEANER + register struct soap_multipart *content; + register size_t count = soap->count; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the message size with attachments, current count=%lu\n", (unsigned long)count)); + if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of DIME attachments\n")); + for (content = soap->dime.first; content; content = content->next) + { count += 12 + ((content->size+3)&(~3)); + if (content->id) + count += ((strlen(content->id)+3)&(~3)); + if (content->type) + count += ((strlen(content->type)+3)&(~3)); + if (content->options) + count += ((((unsigned char)content->options[2] << 8) | ((unsigned char)content->options[3]))+7)&(~3); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of DIME attachment content is %lu bytes\n", (unsigned long)content->size)); + } + } + if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary) + { register size_t n = strlen(soap->mime.boundary); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of MIME attachments\n")); + for (content = soap->mime.first; content; content = content->next) + { register const char *s; + /* count \r\n--boundary\r\n */ + count += 6 + n; + /* count Content-Type: ...\r\n */ + if (content->type) + count += 16 + strlen(content->type); + /* count Content-Transfer-Encoding: ...\r\n */ + s = soap_code_str(mime_codes, content->encoding); + if (s) + count += 29 + strlen(s); + /* count Content-ID: ...\r\n */ + if (content->id) + count += 14 + strlen(content->id); + /* count Content-Location: ...\r\n */ + if (content->location) + count += 20 + strlen(content->location); + /* count Content-Description: ...\r\n */ + if (content->description) + count += 23 + strlen(content->description); + /* count \r\n...content */ + count += 2 + content->size; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of MIME attachment content is %lu bytes\n", (unsigned long)content->size)); + } + /* count \r\n--boundary-- */ + count += 6 + n; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New count is %lu bytes\n", (unsigned long)count)); + return count; +#else + return soap->count; +#endif +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static int +soap_putdimefield(struct soap *soap, const char *s, size_t n) +{ if (soap_send_raw(soap, s, n)) + return soap->error; + return soap_send_raw(soap, SOAP_STR_PADDING, -(long)n&3); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_dime_option(struct soap *soap, unsigned short optype, const char *option) +{ size_t n; + char *s = NULL; + if (option) + { n = strlen(option); + s = (char*)soap_malloc(soap, n + 5); + if (s) + { s[0] = optype >> 8; + s[1] = optype & 0xFF; + s[2] = n >> 8; + s[3] = n & 0xFF; + strcpy(s + 4, option); + } + } + return s; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putdimehdr(struct soap *soap) +{ unsigned char tmp[12]; + size_t optlen = 0, idlen = 0, typelen = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Put DIME header id='%s'\n", soap->dime.id?soap->dime.id:"")); + if (soap->dime.options) + optlen = (((unsigned char)soap->dime.options[2] << 8) | ((unsigned char)soap->dime.options[3])) + 4; + if (soap->dime.id) + idlen = strlen(soap->dime.id); + if (soap->dime.type) + typelen = strlen(soap->dime.type); + tmp[0] = SOAP_DIME_VERSION | (soap->dime.flags & 0x7); + tmp[1] = soap->dime.flags & 0xF0; + tmp[2] = optlen >> 8; + tmp[3] = optlen & 0xFF; + tmp[4] = idlen >> 8; + tmp[5] = idlen & 0xFF; + tmp[6] = typelen >> 8; + tmp[7] = typelen & 0xFF; + tmp[8] = soap->dime.size >> 24; + tmp[9] = (soap->dime.size >> 16) & 0xFF; + tmp[10] = (soap->dime.size >> 8) & 0xFF; + tmp[11] = soap->dime.size & 0xFF; + if (soap_send_raw(soap, (char*)tmp, 12) + || soap_putdimefield(soap, soap->dime.options, optlen) + || soap_putdimefield(soap, soap->dime.id, idlen) + || soap_putdimefield(soap, soap->dime.type, typelen)) + return soap->error; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putdime(struct soap *soap) +{ struct soap_multipart *content; + if (!(soap->mode & SOAP_ENC_DIME)) + return SOAP_OK; + for (content = soap->dime.first; content; content = content->next) + { void *handle; + soap->dime.size = content->size; + soap->dime.id = content->id; + soap->dime.type = content->type; + soap->dime.options = content->options; + soap->dime.flags = SOAP_DIME_VERSION | SOAP_DIME_MEDIA; + if (soap->fdimereadopen && ((handle = soap->fdimereadopen(soap, (void*)content->ptr, content->id, content->type, content->options)) || soap->error)) + { size_t size = content->size; + if (!handle) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadopen failed\n")); + return soap->error; + } + if (!size && ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE)) + { size_t chunksize = sizeof(soap->tmpbuf); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming DIME\n")); + do + { size = soap->fdimeread(soap, handle, soap->tmpbuf, chunksize); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread returned %lu bytes\n", (unsigned long)size)); + if (size < chunksize) + { soap->dime.flags &= ~SOAP_DIME_CF; + if (!content->next) + soap->dime.flags |= SOAP_DIME_ME; + } + else + soap->dime.flags |= SOAP_DIME_CF; + soap->dime.size = size; + if (soap_putdimehdr(soap) + || soap_putdimefield(soap, soap->tmpbuf, size)) + break; + if (soap->dime.id) + { soap->dime.flags &= ~(SOAP_DIME_MB | SOAP_DIME_MEDIA); + soap->dime.id = NULL; + soap->dime.type = NULL; + soap->dime.options = NULL; + } + } while (size >= chunksize); + } + else + { if (!content->next) + soap->dime.flags |= SOAP_DIME_ME; + if (soap_putdimehdr(soap)) + return soap->error; + do + { size_t bufsize; + if (size < sizeof(soap->tmpbuf)) + bufsize = size; + else + bufsize = sizeof(soap->tmpbuf); + if (!(bufsize = soap->fdimeread(soap, handle, soap->tmpbuf, bufsize))) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size)); + soap->error = SOAP_EOF; + break; + } + if (soap_send_raw(soap, soap->tmpbuf, bufsize)) + break; + size -= bufsize; + } while (size); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n")); + soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3); + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n")); + if (soap->fdimereadclose) + soap->fdimereadclose(soap, handle); + } + else + { if (!content->next) + soap->dime.flags |= SOAP_DIME_ME; + if (soap_putdimehdr(soap) + || soap_putdimefield(soap, (char*)content->ptr, content->size)) + return soap->error; + } + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static char * +soap_getdimefield(struct soap *soap, size_t n) +{ register soap_wchar c; + register int i; + register char *s; + char *p = NULL; + if (n) + { p = (char*)soap_malloc(soap, n + 1); + if (p) + { s = p; + for (i = n; i > 0; i--) + { if ((int)(c = soap_get1(soap)) == EOF) + { soap->error = SOAP_EOF; + return NULL; + } + *s++ = (char)c; + } + *s = '\0'; + if ((soap->error = soap_move(soap, -(long)n&3))) + return NULL; + } + else + soap->error = SOAP_EOM; + } + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getdimehdr(struct soap *soap) +{ register soap_wchar c; + register char *s; + register int i; + unsigned char tmp[12]; + size_t optlen, idlen, typelen; + if (!(soap->mode & SOAP_ENC_DIME)) + return soap->error = SOAP_DIME_END; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME header\n")); + if (soap->dime.buflen || soap->dime.chunksize) + { if (soap_move(soap, (long)(soap->dime.size - soap_tell(soap)))) + return soap->error = SOAP_EOF; + soap_unget(soap, soap_getchar(soap)); /* skip padding and get hdr */ + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... From chunked\n")); + return SOAP_OK; + } + s = (char*)tmp; + for (i = 12; i > 0; i--) + { if ((int)(c = soap_getchar(soap)) == EOF) + return soap->error = SOAP_EOF; + *s++ = (char)c; + } + if ((tmp[0] & 0xF8) != SOAP_DIME_VERSION) + return soap->error = SOAP_DIME_MISMATCH; + soap->dime.flags = (tmp[0] & 0x7) | (tmp[1] & 0xF0); + optlen = (tmp[2] << 8) | tmp[3]; + idlen = (tmp[4] << 8) | tmp[5]; + typelen = (tmp[6] << 8) | tmp[7]; + soap->dime.size = (tmp[8] << 24) | (tmp[9] << 16) | (tmp[10] << 8) | tmp[11]; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME size=%lu flags=0x%X\n", (unsigned long)soap->dime.size, soap->dime.flags)); + if (!(soap->dime.options = soap_getdimefield(soap, optlen)) && soap->error) + return soap->error; + if (!(soap->dime.id = soap_getdimefield(soap, idlen)) && soap->error) + return soap->error; + if (!(soap->dime.type = soap_getdimefield(soap, typelen)) && soap->error) + return soap->error; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME id=%s, type=%s, options=%s\n", soap->dime.id?soap->dime.id:"", soap->dime.type?soap->dime.type:"", soap->dime.options?soap->dime.options+4:"")); + if (soap->dime.flags & SOAP_DIME_ME) + soap->mode &= ~SOAP_ENC_DIME; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getdime(struct soap *soap) +{ while (soap->dime.flags & SOAP_DIME_CF) + { if (soap_getdimehdr(soap)) + return soap->error; + if (soap_move(soap, soap->dime.size)) + return soap->error = SOAP_EOF; + } + if (soap_move(soap, ((soap->dime.size+3)&(~3))-soap_tell(soap))) + return soap->error = SOAP_EOF; + for (;;) + { register struct soap_multipart *content; + if (soap_getdimehdr(soap)) + break; + if (soap->fdimewriteopen && ((soap->dime.ptr = (char*)soap->fdimewriteopen(soap, soap->dime.id, soap->dime.type, soap->dime.options)) || soap->error)) + { const char *id, *type, *options; + size_t size, n; + if (!soap->dime.ptr) + return soap->error; + id = soap->dime.id; + type = soap->dime.type; + options = soap->dime.options; + for (;;) + { size = soap->dime.size; + for (;;) + { n = soap->buflen - soap->bufidx; + if (size < n) + n = size; + if ((soap->error = soap->fdimewrite(soap, (void*)soap->dime.ptr, soap->buf + soap->bufidx, n))) + break; + size -= n; + if (!size) + { soap->bufidx += n; + break; + } + if (soap_recv(soap)) + { soap->error = SOAP_EOF; + goto end; + } + } + if (soap_move(soap, -(long)soap->dime.size&3)) + { soap->error = SOAP_EOF; + break; + } + if (!(soap->dime.flags & SOAP_DIME_CF)) + break; + if (soap_getdimehdr(soap)) + break; + } +end: + if (soap->fdimewriteclose) + soap->fdimewriteclose(soap, (void*)soap->dime.ptr); + soap->dime.size = 0; + soap->dime.id = id; + soap->dime.type = type; + soap->dime.options = options; + } + else if (soap->dime.flags & SOAP_DIME_CF) + { const char *id, *type, *options; + register soap_wchar c; + register char *s; + register int i; + id = soap->dime.id; + type = soap->dime.type; + options = soap->dime.options; + if (soap_new_block(soap)) + return SOAP_EOM; + for (;;) + { s = (char*)soap_push_block(soap, soap->dime.size); + if (!s) + return soap->error = SOAP_EOM; + for (i = soap->dime.size; i > 0; i--) + { if ((int)(c = soap_get1(soap)) == EOF) + return soap->error = SOAP_EOF; + *s++ = (char)c; + } + if (soap_move(soap, -(long)soap->dime.size&3)) + return soap->error = SOAP_EOF; + if (!(soap->dime.flags & SOAP_DIME_CF)) + break; + if (soap_getdimehdr(soap)) + return soap->error; + } + soap->dime.size = soap->blist->size++; /* allocate one more for '\0' */ + if (!(soap->dime.ptr = soap_save_block(soap, NULL, 0))) + return soap->error; + soap->dime.ptr[soap->dime.size] = '\0'; /* force 0-terminated */ + soap->dime.id = id; + soap->dime.type = type; + soap->dime.options = options; + } + else + soap->dime.ptr = soap_getdimefield(soap, soap->dime.size); + content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, soap->dime.ptr, soap->dime.size); + if (!content) + return soap->error = SOAP_EOM; + content->id = soap->dime.id; + content->type = soap->dime.type; + content->options = soap->dime.options; + if (soap->error) + return soap->error; + soap_resolve_attachment(soap, content); + } + if (soap->error != SOAP_DIME_END) + return soap->error; + return soap->error = SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getmimehdr(struct soap *soap) +{ struct soap_multipart *content; + do + { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) + return soap->error; + } + while (!*soap->msgbuf); + if (soap->msgbuf[0] == '-' && soap->msgbuf[1] == '-') + { char *s = soap->msgbuf + strlen(soap->msgbuf) - 1; + /* remove white space */ + while (soap_blank(*s)) + s--; + s[1] = '\0'; + if (soap->mime.boundary) + { if (strcmp(soap->msgbuf + 2, soap->mime.boundary)) + return soap->error = SOAP_MIME_ERROR; + } + else + soap->mime.boundary = soap_strdup(soap, soap->msgbuf + 2); + if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) + return soap->error; + } + if (soap_set_mime_attachment(soap, NULL, 0, SOAP_MIME_NONE, NULL, NULL, NULL, NULL)) + return soap->error = SOAP_EOM; + content = soap->mime.last; + for (;;) + { register char *key = soap->msgbuf; + register char *val; + if (!*key) + break; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "MIME header: %s\n", key)); + val = strchr(soap->msgbuf, ':'); + if (val) + { *val = '\0'; + do val++; + while (*val && *val <= 32); + if (!soap_tag_cmp(key, "Content-ID")) + content->id = soap_strdup(soap, val); + else if (!soap_tag_cmp(key, "Content-Location")) + content->location = soap_strdup(soap, val); + else if (!soap_tag_cmp(key, "Content-Disposition")) + content->id = soap_strdup(soap, soap_get_header_attribute(soap, val, "name")); + else if (!soap_tag_cmp(key, "Content-Type")) + content->type = soap_strdup(soap, val); + else if (!soap_tag_cmp(key, "Content-Description")) + content->description = soap_strdup(soap, val); + else if (!soap_tag_cmp(key, "Content-Transfer-Encoding")) + content->encoding = (enum soap_mime_encoding)soap_code_int(mime_codes, val, (long)SOAP_MIME_NONE); + } + if (soap_getline(soap, key, sizeof(soap->msgbuf))) + return soap->error; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getmime(struct soap *soap) +{ while (soap_get_mime_attachment(soap, NULL)) + ; + return soap->error; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_post_check_mime_attachments(struct soap *soap) +{ soap->imode |= SOAP_MIME_POSTCHECK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_check_mime_attachments(struct soap *soap) +{ if (soap->mode & SOAP_MIME_POSTCHECK) + return soap_get_mime_attachment(soap, NULL) != NULL; + return 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +struct soap_multipart * +SOAP_FMAC2 +soap_get_mime_attachment(struct soap *soap, void *handle) +{ register soap_wchar c = 0; + register size_t i, m = 0; + register char *s, *t = NULL; + register struct soap_multipart *content; + register short flag = 0; + if (!(soap->mode & SOAP_ENC_MIME)) + return NULL; + content = soap->mime.last; + if (!content) + { if (soap_getmimehdr(soap)) + return NULL; + content = soap->mime.last; + } + else if (content != soap->mime.first) + { if (soap->fmimewriteopen && ((content->ptr = (char*)soap->fmimewriteopen(soap, (void*)handle, content->id, content->type, content->description, content->encoding)) || soap->error)) + { if (!content->ptr) + return NULL; + } + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Parsing MIME content id=%s type=%s\n", content->id?content->id:"", content->type?content->type:"")); + if (!content->ptr && soap_new_block(soap)) + { soap->error = SOAP_EOM; + return NULL; + } + for (;;) + { if (content->ptr) + s = soap->tmpbuf; + else if (!(s = (char*)soap_push_block(soap, sizeof(soap->tmpbuf)))) + { soap->error = SOAP_EOM; + return NULL; + } + for (i = 0; i < sizeof(soap->tmpbuf); i++) + { if (m > 0) + { *s++ = *t++; + m--; + } + else + { if (!flag) + { c = soap_get1(soap); + if ((int)c == EOF) + { soap->error = SOAP_EOF; + return NULL; + } + } + if (flag || c == '\r') + { t = soap->msgbuf; + memset(t, 0, sizeof(soap->msgbuf)); + strcpy(t, "\n--"); + if (soap->mime.boundary) + strncat(t, soap->mime.boundary, sizeof(soap->msgbuf)-4); + do c = soap_getchar(soap); + while (c == *t++); + if ((int)c == EOF) + { soap->error = SOAP_EOF; + return NULL; + } + if (!*--t) + goto end; + *t = (char)c; + flag = (c == '\r'); + m = t - soap->msgbuf + 1 - flag; + t = soap->msgbuf; + c = '\r'; + } + *s++ = (char)c; + } + } + if (content->ptr && soap->fmimewrite) + { if ((soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i))) + break; + } + } +end: + *s = '\0'; /* force 0-terminated */ + if (content->ptr) + { if (!soap->error && soap->fmimewrite) + soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i); + if (soap->fmimewriteclose) + soap->fmimewriteclose(soap, (void*)content->ptr); + if (soap->error) + return NULL; + } + else + { content->size = soap_size_block(soap, i+1)-1; + content->ptr = soap_save_block(soap, NULL, 0); + } + soap_resolve_attachment(soap, content); + if (c == '-' && soap_getchar(soap) == '-') + { soap->mode &= ~SOAP_ENC_MIME; + if ((soap->mode & SOAP_MIME_POSTCHECK) && soap_end_recv(soap)) + return NULL; + } + else + { while (c != '\r' && (int)c != EOF && soap_blank(c)) + c = soap_getchar(soap); + if (c != '\r' || soap_getchar(soap) != '\n') + { soap->error = SOAP_MIME_ERROR; + return NULL; + } + if (soap_getmimehdr(soap)) + return NULL; + } + return content; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_match_cid(struct soap *soap, const char *s, const char *t) +{ register size_t n; + if (!s) + return 1; + if (!strcmp(s, t)) + return 0; + if (!strncmp(s, "cid:", 4)) + s += 4; + n = strlen(t); + if (*t == '<') + { t++; + n -= 2; + } + if (!strncmp(s, t, n) && !s[n]) + return 0; + soap_decode(soap->tmpbuf, sizeof(soap->tmpbuf), s, SOAP_STR_EOS); + if (!strncmp(soap->tmpbuf, t, n) && !soap->tmpbuf[n]) + return 0; + return 1; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static void +soap_resolve_attachment(struct soap *soap, struct soap_multipart *content) +{ if (content->id) + { register struct soap_xlist **xp = &soap->xlist; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving attachment data for id=%s\n", content->id)); + while (*xp) + { register struct soap_xlist *xq = *xp; + if (!soap_match_cid(soap, xq->id, content->id)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Found matching attachment %s for content id=%s\n", xq->id, content->id)); + *xp = xq->next; + *xq->ptr = (unsigned char*)content->ptr; + *xq->size = (int)content->size; + *xq->type = (char*)content->type; + if (content->options) + *xq->options = (char*)content->options; + else + *xq->options = (char*)content->description; + SOAP_FREE(soap, xq); + } + else + xp = &(*xp)->next; + } + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putmimehdr(struct soap *soap, struct soap_multipart *content) +{ const char *s; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "MIME attachment type=%s\n", content->type?content->type:"")); + if (soap_send3(soap, "\r\n--", soap->mime.boundary, "\r\n")) + return soap->error; + if (content->type && soap_send3(soap, "Content-Type: ", content->type, "\r\n")) + return soap->error; + s = soap_code_str(mime_codes, content->encoding); + if (s && soap_send3(soap, "Content-Transfer-Encoding: ", s, "\r\n")) + return soap->error; + if (content->id && soap_send3(soap, "Content-ID: ", content->id, "\r\n")) + return soap->error; + if (content->location && soap_send3(soap, "Content-Location: ", content->location, "\r\n")) + return soap->error; + if (content->description && soap_send3(soap, "Content-Description: ", content->description, "\r\n")) + return soap->error; + return soap_send_raw(soap, "\r\n", 2); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putmime(struct soap *soap) +{ struct soap_multipart *content; + if (!(soap->mode & SOAP_ENC_MIME) || !soap->mime.boundary) + return SOAP_OK; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending MIME attachments\n")); + for (content = soap->mime.first; content; content = content->next) + { void *handle; + if (soap->fmimereadopen && ((handle = soap->fmimereadopen(soap, (void*)content->ptr, content->id, content->type, content->description)) || soap->error)) + { size_t size = content->size; + if (!handle) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimereadopen failed\n")); + return soap->error; + } + if (soap_putmimehdr(soap, content)) + return soap->error; + if (!size) + { if ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming MIME\n")); + do + { size = soap->fmimeread(soap, handle, soap->tmpbuf, sizeof(soap->tmpbuf)); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread returned %lu bytes\n", (unsigned long)size)); + if (soap_send_raw(soap, soap->tmpbuf, size)) + break; + } while (size); + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error: cannot chunk streaming MIME (no HTTP chunking)\n")); + } + } + else + { do + { size_t bufsize; + if (size < sizeof(soap->tmpbuf)) + bufsize = size; + else + bufsize = sizeof(soap->tmpbuf); + if (!(bufsize = soap->fmimeread(soap, handle, soap->tmpbuf, bufsize))) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size)); + soap->error = SOAP_EOF; + break; + } + if (soap_send_raw(soap, soap->tmpbuf, bufsize)) + break; + size -= bufsize; + } while (size); + } + if (soap->fmimereadclose) + soap->fmimereadclose(soap, handle); + } + else + { if (soap_putmimehdr(soap, content) + || soap_send_raw(soap, content->ptr, content->size)) + return soap->error; + } + } + return soap_send3(soap, "\r\n--", soap->mime.boundary, "--"); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_dime(struct soap *soap) +{ soap->omode |= SOAP_ENC_DIME; + soap->dime.first = NULL; + soap->dime.last = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_mime(struct soap *soap, const char *boundary, const char *start) +{ soap->omode |= SOAP_ENC_MIME; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = soap_strdup(soap, boundary); + soap->mime.start = soap_strdup(soap, start); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_clr_dime(struct soap *soap) +{ soap->omode &= ~SOAP_ENC_DIME; + soap->dime.first = NULL; + soap->dime.last = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_clr_mime(struct soap *soap) +{ soap->omode &= ~SOAP_ENC_MIME; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = NULL; + soap->mime.start = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static struct soap_multipart* +soap_new_multipart(struct soap *soap, struct soap_multipart **first, struct soap_multipart **last, char *ptr, size_t size) +{ struct soap_multipart *content; + content = (struct soap_multipart*)soap_malloc(soap, sizeof(struct soap_multipart)); + if (content) + { content->next = NULL; + content->ptr = ptr; + content->size = size; + content->id = NULL; + content->type = NULL; + content->options = NULL; + content->encoding = SOAP_MIME_NONE; + content->location = NULL; + content->description = NULL; + if (!*first) + *first = content; + if (*last) + (*last)->next = content; + *last = content; + } + return content; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_dime_attachment(struct soap *soap, char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option) +{ struct soap_multipart *content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, ptr, size); + if (!content) + return SOAP_EOM; + content->id = soap_strdup(soap, id); + content->type = soap_strdup(soap, type); + content->options = soap_dime_option(soap, optype, option); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_mime_attachment(struct soap *soap, char *ptr, size_t size, enum soap_mime_encoding encoding, const char *type, const char *id, const char *location, const char *description) +{ struct soap_multipart *content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, ptr, size); + if (!content) + return SOAP_EOM; + content->id = soap_strdup(soap, id); + content->type = soap_strdup(soap, type); + content->encoding = encoding; + content->location = soap_strdup(soap, location); + content->description = soap_strdup(soap, description); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +struct soap_multipart* +SOAP_FMAC2 +soap_next_multipart(struct soap_multipart *content) +{ if (content) + return content->next; + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static void +soap_select_mime_boundary(struct soap *soap) +{ while (!soap->mime.boundary || soap_valid_mime_boundary(soap)) + { register char *s = soap->mime.boundary; + register size_t n = 0; + if (s) + n = strlen(s); + if (n < 16) + { n = 64; + s = soap->mime.boundary = (char*)soap_malloc(soap, n + 1); + if (!s) + return; + } + strcpy(s, "=="); + s += 2; + n -= 4; + while (n) + { *s++ = soap_base64o[soap_random & 0x3F]; + n--; + } + strcpy(s, "=="); + } + if (!soap->mime.start) + soap->mime.start = ""; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static int +soap_valid_mime_boundary(struct soap *soap) +{ register struct soap_multipart *content; + register size_t k; + if (soap->fmimeread) + return SOAP_OK; + k = strlen(soap->mime.boundary); + for (content = soap->mime.first; content; content = content->next) + { if (content->ptr && content->size >= k) + { register const char *p = (const char*)content->ptr; + register size_t i; + for (i = 0; i < content->size - k; i++, p++) + { if (!strncmp(p, soap->mime.boundary, k)) + return SOAP_ERR; + } + } + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************\ + * + * HTTP cookie handling + * +\******************************************************************************/ + +#ifdef WITH_COOKIES +/******************************************************************************/ +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_encode_cookie(const char *s, char *t, size_t len) +{ register int c; + register size_t n = len; + while ((c = *s++) && --n > 0) + { if (c > ' ' && c < 128 && !strchr("()<>@,;:\\\"/[]?={}", c)) + *t++ = c; + else if (n > 2) + { *t++ = '%'; + *t++ = (c >> 4) + (c > 159 ? '7' : '0'); + c &= 0xF; + *t++ = c + (c > 9 ? '7' : '0'); + n -= 2; + } + else + break; + } + *t = '\0'; + return len - n; +} + +/******************************************************************************/ +SOAP_FMAC1 +struct soap_cookie* +SOAP_FMAC2 +soap_cookie(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + size_t n; + if (!domain) + domain = soap->cookie_domain; + if (!path) + path = soap->cookie_path; + if (!path) + path = SOAP_STR_EOS; + else if (*path == '/') + path++; + n = strlen(path); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Search cookie %s domain=%s path=%s\n", name, domain?domain:"(null)", path?path:"(null)")); + for (p = soap->cookies; p; p = p->next) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie in database: %s=%s domain=%s path=%s env=%hd\n", p->name, p->value?p->value:"(null)", p->domain?p->domain:"(null)", p->path?p->path:"(null)", p->env)); + if (!strcmp(p->name, name) + && p->domain + && p->path + && !strcmp(p->domain, domain) + && !strncmp(p->path, path, n)) + break; + } + return p; +} + +/******************************************************************************/ +SOAP_FMAC1 +struct soap_cookie* +SOAP_FMAC2 +soap_set_cookie(struct soap *soap, const char *name, const char *value, const char *domain, const char *path) +{ struct soap_cookie **p, *q; + int n; + if (!domain) + domain = soap->cookie_domain; + if (!path) + path = soap->cookie_path; + if (!path) + path = SOAP_STR_EOS; + else if (*path == '/') + path++; + q = soap_cookie(soap, name, domain, path); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set %scookie: %s=%s domain=%s path=%s\n", q ? "" : "new ", name, value?value:"(null)", domain?domain:"(null)", path?path:"(null)")); + if (!q) + { if ((q = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie)))) + { if ((q->name = (char*)SOAP_MALLOC(soap, strlen(name)+1))) + strcpy(q->name, name); + q->value = NULL; + q->domain = NULL; + q->path = NULL; + q->expire = 0; + q->maxage = -1; + q->version = 1; + q->secure = 0; + q->modified = 0; + for (p = &soap->cookies, n = soap->cookie_max; *p && n; p = &(*p)->next, n--) + if (!strcmp((*p)->name, name) && (*p)->path && path && strcmp((*p)->path, path) < 0) + break; + if (n) + { q->next = *p; + *p = q; + } + else + { SOAP_FREE(soap, q->name); + SOAP_FREE(soap, q); + q = NULL; + } + } + } + else + q->modified = 1; + if (q) + { if (q->value) + { SOAP_FREE(soap, q->value); + q->value = NULL; + } + if (q->domain) + { SOAP_FREE(soap, q->domain); + q->domain = NULL; + } + if (q->path) + { SOAP_FREE(soap, q->path); + q->path = NULL; + } + if (value && *value && (q->value = (char*)SOAP_MALLOC(soap, strlen(value)+1))) + strcpy(q->value, value); + if (domain && (q->domain = (char*)SOAP_MALLOC(soap, strlen(domain)+1))) + strcpy(q->domain, domain); + if (path && (q->path = (char*)SOAP_MALLOC(soap, strlen(path)+1))) + strcpy(q->path, path); + q->session = 1; + q->env = 0; + } + return q; +} + +/******************************************************************************/ +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_clr_cookie(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie **p, *q; + if (!domain) + domain = soap->cookie_domain; + if (!domain) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error in clear cookie %s: cookie domain not set\n", name?name:"(null)")); + return; + } + if (!path) + path = soap->cookie_path; + if (!path) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error in clear cookie %s: cookie path not set\n", name?name:"(null)")); + return; + } + if (*path == '/') + path++; + for (p = &soap->cookies, q = *p; q; q = *p) + { if (!strcmp(q->name, name) && !strcmp(q->domain, domain) && !strncmp(q->path, path, strlen(q->path))) + { if (q->value) + SOAP_FREE(soap, q->value); + if (q->domain) + SOAP_FREE(soap, q->domain); + if (q->path) + SOAP_FREE(soap, q->path); + *p = q->next; + SOAP_FREE(soap, q); + } + else + p = &q->next; + } +} + +/******************************************************************************/ +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + return p->value; + return NULL; +} + +/******************************************************************************/ +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_env_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path)) && p->env) + return p->value; + return NULL; +} + +/******************************************************************************/ +SOAP_FMAC1 +time_t +SOAP_FMAC2 +soap_cookie_expire(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + return p->expire; + return -1; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_cookie_expire(struct soap *soap, const char *name, long expire, const char *domain, const char *path) +{ struct soap_cookie *p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set cookie expiration max-age %ld: %s domain=%s path=%s\n", expire, name, domain?domain:"(null)", path?path:"(null)")); + if ((p = soap_cookie(soap, name, domain, path))) + { p->maxage = expire; + p->modified = 1; + return SOAP_OK; + } + return SOAP_ERR; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + { p->session = 1; + p->modified = 1; + return SOAP_OK; + } + return SOAP_ERR; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_clr_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + { p->session = 0; + p->modified = 1; + return SOAP_OK; + } + return SOAP_ERR; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putsetcookies(struct soap *soap) +{ struct soap_cookie *p; + char *s, tmp[4096]; + const char *t; + for (p = soap->cookies; p; p = p->next) + { + if (p->modified +#ifdef WITH_OPENSSL + || (!p->env && !soap->ssl == !p->secure) +#endif + ) + { s = tmp; + if (p->name) + s += soap_encode_cookie(p->name, s, tmp-s+4064); + if (p->value && *p->value) + { *s++ = '='; + s += soap_encode_cookie(p->value, s, tmp-s+4064); + } + if (p->domain && (int)strlen(p->domain) < tmp-s+4064) + { strcpy(s, ";Domain="); + strcat(s, p->domain); + } + else if (soap->cookie_domain && (int)strlen(soap->cookie_domain) < tmp-s+4064) + { strcpy(s, ";Domain="); + strcat(s, soap->cookie_domain); + } + strcat(s, ";Path=/"); + s += strlen(s); + if (p->path) + t = p->path; + else + t = soap->cookie_path; + if (t) + { if (*t == '/') + t++; + if ((int)strlen(t) < tmp-s+4064) + { if (strchr(t, '%')) /* already URL encoded? */ + { strcpy(s, t); + s += strlen(s); + } + else + s += soap_encode_cookie(t, s, tmp-s+4064); + } + } + if (p->version > 0 && s-tmp < 4060) + { sprintf(s, ";Version=%u", p->version); + s += strlen(s); + } + if (p->maxage >= 0 && s-tmp < 4060) + { sprintf(s, ";Max-Age=%ld", p->maxage); + s += strlen(s); + } + if (s-tmp < 4073 + && (p->secure +#ifdef WITH_OPENSSL + || soap->ssl +#endif + )) + strcpy(s, ";Secure"); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set-Cookie: %s\n", tmp)); + if ((soap->error = soap->fposthdr(soap, "Set-Cookie", tmp))) + return soap->error; + } + } + return SOAP_OK; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putcookies(struct soap *soap, const char *domain, const char *path, int secure) +{ struct soap_cookie **p, *q; + unsigned int version = 0; + time_t now = time(NULL); + char *s, tmp[4096]; + p = &soap->cookies; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending cookies for domain=%s path=%s\n", domain, path)); + if (*path == '/') + path++; + while ((q = *p)) + { if (q->expire && now > q->expire) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie %s expired\n", q->name)); + SOAP_FREE(soap, q->name); + if (q->value) + SOAP_FREE(soap, q->value); + if (q->domain) + SOAP_FREE(soap, q->domain); + if (q->path) + SOAP_FREE(soap, q->path); + *p = q->next; + SOAP_FREE(soap, q); + } + else + { int flag; + char *t = q->domain; + size_t n = 0; + if (!t) + flag = 1; + else + { const char *r = strchr(t, ':'); + if (r) + n = r - t; + else + n = strlen(t); + flag = !strncmp(t, domain, n); + } + /* domain-level cookies */ + if (!flag) + { struct hostent *hostent = gethostbyname(domain); + if (hostent) + { char *r = strchr(hostent->h_name, '.'); + if (!r) + r = hostent->h_name; + flag = !strncmp(t, r, n); + } + } + if (flag + && (!q->path || !strncmp(q->path, path, strlen(q->path))) + && (!q->secure || secure)) + { s = tmp; + if (q->version != version) + { sprintf(s, "$Version=%u;", q->version); + version = q->version; + } + if (q->name) + s += soap_encode_cookie(q->name, s, tmp-s+4080); + if (q->value && *q->value) + { *s++ = '='; + s += soap_encode_cookie(q->value, s, tmp-s+4080); + } + if (q->path && *q->path && (int)strlen(q->path) < tmp-s+4080) + { sprintf(s, ";$Path=\"/%s\"", (*q->path == '/' ? q->path + 1 : q->path)); + s += strlen(s); + } + if (q->domain && (int)strlen(q->domain) < tmp-s+4080) + sprintf(s, ";$Domain=\"%s\"", q->domain); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie: %s\n", tmp)); + if ((soap->error = soap->fposthdr(soap, "Cookie", tmp))) + return soap->error; + } + p = &q->next; + } + } + return SOAP_OK; +} + +/******************************************************************************/ +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_getcookies(struct soap *soap, const char *val) +{ struct soap_cookie *p = NULL, *q; + const char *s; + char *t, tmp[4096]; /* cookie size is up to 4096 bytes [RFC2109] */ + char *domain = NULL; + char *path = NULL; + unsigned int version = 0; + time_t now = time(NULL); + if (!val) + return; + s = val; + while (*s) + { s = soap_decode_key(tmp, sizeof(tmp), s); + if (!soap_tag_cmp(tmp, "$Version")) + { if ((s = soap_decode_val(tmp, sizeof(tmp), s))) + { if (p) + p->version = (int)atol(tmp); + else + version = (int)atol(tmp); + } + } + else if (!soap_tag_cmp(tmp, "$Path")) + { s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) + strcpy(t, tmp); + } + else + t = NULL; + if (p) + { if (p->path) + SOAP_FREE(soap, p->path); + p->path = t; + } + else + { if (path) + SOAP_FREE(soap, path); + path = t; + } + } + else if (!soap_tag_cmp(tmp, "$Domain")) + { s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) + strcpy(t, tmp); + } + else + t = NULL; + if (p) + { if (p->domain) + SOAP_FREE(soap, p->domain); + p->domain = t; + } + else + { if (domain) + SOAP_FREE(soap, domain); + domain = t; + } + } + else if (p && !soap_tag_cmp(tmp, "Path")) + { if (p->path) + SOAP_FREE(soap, p->path); + s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { if ((p->path = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) + strcpy(p->path, tmp); + } + else + p->path = NULL; + } + else if (p && !soap_tag_cmp(tmp, "Domain")) + { if (p->domain) + SOAP_FREE(soap, p->domain); + s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { if ((p->domain = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) + strcpy(p->domain, tmp); + } + else + p->domain = NULL; + } + else if (p && !soap_tag_cmp(tmp, "Version")) + { s = soap_decode_val(tmp, sizeof(tmp), s); + p->version = (unsigned int)atol(tmp); + } + else if (p && !soap_tag_cmp(tmp, "Max-Age")) + { s = soap_decode_val(tmp, sizeof(tmp), s); + p->expire = now + atol(tmp); + } + else if (p && !soap_tag_cmp(tmp, "Expires")) + { struct tm T; + char a[3]; + static const char mns[] = "anebarprayunulugepctovec"; + s = soap_decode_val(tmp, sizeof(tmp), s); + if (strlen(tmp) > 20) + { memset((void*)&T, 0, sizeof(T)); + a[0] = tmp[4]; + a[1] = tmp[5]; + a[2] = '\0'; + T.tm_mday = (int)atol(a); + a[0] = tmp[8]; + a[1] = tmp[9]; + T.tm_mon = (strstr(mns, a) - mns) / 2; + a[0] = tmp[11]; + a[1] = tmp[12]; + T.tm_year = 100 + (int)atol(a); + a[0] = tmp[13]; + a[1] = tmp[14]; + T.tm_hour = (int)atol(a); + a[0] = tmp[16]; + a[1] = tmp[17]; + T.tm_min = (int)atol(a); + a[0] = tmp[19]; + a[1] = tmp[20]; + T.tm_sec = (int)atol(a); + p->expire = soap_timegm(&T); + } + } + else if (p && !soap_tag_cmp(tmp, "Secure")) + p->secure = 1; + else + { if (p) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie %s=%s domain=%s path=%s expire=%ld secure=%d\n", p->name, p->value?p->value:"(null)", p->domain?p->domain:"(null)", p->path?p->path:"(null)", p->expire, p->secure)); + if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path))) + { q->version = p->version; + q->expire = p->expire; + q->secure = p->secure; + q->env = 1; + } + if (p->name) + SOAP_FREE(soap, p->name); + if (p->value) + SOAP_FREE(soap, p->value); + if (p->domain) + SOAP_FREE(soap, p->domain); + if (p->path) + SOAP_FREE(soap, p->path); + SOAP_FREE(soap, p); + } + if ((p = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie)))) + { p->name = (char*)SOAP_MALLOC(soap, strlen(tmp)+1); + strcpy(p->name, tmp); + s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { p->value = (char*)SOAP_MALLOC(soap, strlen(tmp)+1); + strcpy(p->value, tmp); + } + else + p->value = NULL; + if (domain) + p->domain = domain; + else if (*soap->host) + { p->domain = (char*)SOAP_MALLOC(soap, strlen(soap->host)+1); + strcpy(p->domain, soap->host); + } + else + p->domain = NULL; + if (path) + p->path = path; + else if (soap->path && *soap->path) + { p->path = (char*)SOAP_MALLOC(soap, strlen(soap->path)+1); + strcpy(p->path, soap->path); + } + else + { p->path = (char*)SOAP_MALLOC(soap, 2); + strcpy(p->path, "/"); + } + p->expire = 0; + p->secure = 0; + p->version = version; + } + } + } + if (p) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie %s=%s domain=%s path=%s expire=%ld secure=%d\n", p->name, p->value?p->value:"(null)", p->domain?p->domain:"(null)", p->path?p->path:"(null)", p->expire, p->secure)); + if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path))) + { q->version = p->version; + q->expire = p->expire; + q->secure = p->secure; + q->env = 1; + } + if (p->name) + SOAP_FREE(soap, p->name); + if (p->value) + SOAP_FREE(soap, p->value); + if (p->domain) + SOAP_FREE(soap, p->domain); + if (p->path) + SOAP_FREE(soap, p->path); + SOAP_FREE(soap, p); + } + if (domain) + SOAP_FREE(soap, domain); + if (path) + SOAP_FREE(soap, path); +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getenv_cookies(struct soap *soap) +{ struct soap_cookie *p; + const char *s; + char key[4096], val[4096]; /* cookie size is up to 4096 bytes [RFC2109] */ + if (!(s = getenv("HTTP_COOKIE"))) + return SOAP_ERR; + do + { s = soap_decode_key(key, sizeof(key), s); + s = soap_decode_val(val, sizeof(val), s); + p = soap_set_cookie(soap, key, val, NULL, NULL); + if (p) + p->env = 1; + } while (*s); + return SOAP_OK; +} + +/******************************************************************************/ +SOAP_FMAC1 +struct soap_cookie* +SOAP_FMAC2 +soap_copy_cookies(struct soap *copy, struct soap *soap) +{ struct soap_cookie *p, **q, *r; + q = &r; + for (p = soap->cookies; p; p = p->next) + { if (!(*q = (struct soap_cookie*)SOAP_MALLOC(copy, sizeof(struct soap_cookie)))) + return r; + **q = *p; + if (p->name) + { if (((*q)->name = (char*)SOAP_MALLOC(copy, strlen(p->name)+1))) + strcpy((*q)->name, p->name); + } + if (p->value) + { if (((*q)->value = (char*)SOAP_MALLOC(copy, strlen(p->value)+1))) + strcpy((*q)->value, p->value); + } + if (p->domain) + { if (((*q)->domain = (char*)SOAP_MALLOC(copy, strlen(p->domain)+1))) + strcpy((*q)->domain, p->domain); + } + if (p->path) + { if (((*q)->path = (char*)SOAP_MALLOC(copy, strlen(p->path)+1))) + strcpy((*q)->path, p->path); + } + q = &(*q)->next; + } + *q = NULL; + return r; +} + +/******************************************************************************/ +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_free_cookies(struct soap *soap) +{ struct soap_cookie *p; + for (p = soap->cookies; p; p = soap->cookies) + { soap->cookies = p->next; + SOAP_FREE(soap, p->name); + if (p->value) + SOAP_FREE(soap, p->value); + if (p->domain) + SOAP_FREE(soap, p->domain); + if (p->path) + SOAP_FREE(soap, p->path); + SOAP_FREE(soap, p); + } +} + +/******************************************************************************/ +#endif /* WITH_COOKIES */ + +/******************************************************************************/ +#ifdef WITH_GZIP +#ifndef PALM_1 +static int +soap_getgziphdr(struct soap *soap) +{ int i; + soap_wchar c = 0, f = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get gzip header\n")); + for (i = 0; i < 9; i++) + { if ((int)(c = soap_get1(soap) == EOF)) + return soap->error = SOAP_EOF; + if (i == 2) + f = c; + } + if (f & 0x04) /* FEXTRA */ + { for (i = soap_get1(soap) | (soap_get1(soap) << 8); i; i--) + { if ((int)soap_get1(soap) == EOF) + return soap->error = SOAP_EOF; + } + } + if (f & 0x08) /* FNAME */ + { do + c = soap_get1(soap); + while (c && (int)c != EOF); + } + if ((int)c != EOF && (f & 0x10)) /* FCOMMENT */ + { do + c = soap_get1(soap); + while (c && (int)c != EOF); + } + if ((int)c != EOF && (f & 0x01)) /* FHCRC */ + { if ((int)(c = soap_get1(soap)) != EOF) + c = soap_get1(soap); + } + if ((int)c == EOF) + return soap->error = SOAP_EOF; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_begin_recv(struct soap *soap) +{ soap_wchar c; + soap->error = SOAP_OK; + soap_free_temp(soap); + soap_set_local_namespaces(soap); + soap->version = 0; /* don't assume we're parsing SOAP content by default */ +#ifndef WITH_NOIDREF + soap_free_iht(soap); +#endif + if ((soap->imode & SOAP_IO) == SOAP_IO_CHUNK) + soap->omode |= SOAP_IO_CHUNK; + soap->imode &= ~SOAP_IO; + soap->mode = soap->imode; + if (!soap->keep_alive) + { soap->buflen = 0; + soap->bufidx = 0; + } + if (!(soap->mode & SOAP_IO_KEEPALIVE)) + soap->keep_alive = 0; + soap->ahead = 0; + soap->peeked = 0; + soap->level = 0; + soap->part = SOAP_BEGIN; + soap->alloced = 0; + soap->count = 0; + soap->length = 0; + soap->cdata = 0; + *soap->endpoint = '\0'; + soap->action = NULL; + soap->status = 0; +#ifndef WITH_LEANER + soap->dom = NULL; + soap->dime.chunksize = 0; + soap->dime.buflen = 0; + soap->dime.list = NULL; + soap->dime.first = NULL; + soap->dime.last = NULL; + soap->mime.list = NULL; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = NULL; + soap->mime.start = NULL; + soap->xlist = NULL; +#endif +#ifdef WIN32 +#ifndef UNDER_CE +#ifndef WITH_FASTCGI + if (!soap_valid_socket(soap->socket)) +#ifdef __BORLANDC__ + setmode((SOAP_SOCKET)soap->recvfd, O_BINARY); +#else + _setmode((SOAP_SOCKET)soap->recvfd, _O_BINARY); +#endif +#endif +#endif +#endif +#ifdef WITH_ZLIB + soap->mode &= ~SOAP_ENC_ZLIB; + soap->zlib_in = SOAP_ZLIB_NONE; + soap->zlib_out = SOAP_ZLIB_NONE; + soap->d_stream.next_in = Z_NULL; + soap->d_stream.avail_in = 0; + soap->d_stream.next_out = (Byte*)soap->buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + soap->z_ratio_in = 1.0; +#endif +#ifndef WITH_LEANER + if (soap->fprepareinit) + soap->fprepareinit(soap); +#endif + c = soap_getchar(soap); +#ifdef WITH_GZIP + if (c == 0x1F) + { if (soap_getgziphdr(soap)) + return soap->error; + if (inflateInit2(&soap->d_stream, -MAX_WBITS) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; + soap->zlib_state = SOAP_ZLIB_INFLATE; + soap->mode |= SOAP_ENC_ZLIB; + soap->zlib_in = SOAP_ZLIB_GZIP; + soap->z_crc = crc32(0L, NULL, 0); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n")); + memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); + /* should not chunk over plain transport, so why bother to check? */ + /* if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) */ + /* soap->z_buflen = soap->bufidx; */ + /* else */ + soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx); + soap->d_stream.avail_in = soap->buflen - soap->bufidx; + soap->z_buflen = soap->buflen; + soap->buflen = soap->bufidx; + c = soap_getchar(soap); + } +#endif +#ifndef WITH_LEANER + if (c == '-' && soap_get0(soap) == '-') + soap->mode |= SOAP_ENC_MIME; + else if ((c & 0xFFFC) == (SOAP_DIME_VERSION | SOAP_DIME_MB) && (soap_get0(soap) & 0xFFF0) == 0x20) + soap->mode |= SOAP_ENC_DIME; + else +#endif + { while (soap_blank(c)) + c = soap_getchar(soap); + } + if ((int)c == EOF) + return soap->error = SOAP_EOF; + soap_unget(soap, c); +#ifndef WITH_NOHTTP + /* if not XML or (start of)BOM or MIME/DIME/ZLIB, assume HTTP header */ + if (c != '<' && c != 0xEF && !(soap->mode & (SOAP_ENC_MIME | SOAP_ENC_DIME | SOAP_ENC_ZLIB))) + { soap->mode &= ~SOAP_IO; + soap->error = soap->fparse(soap); + if (soap->error && soap->error < SOAP_STOP) + { soap->keep_alive = 0; /* force close later */ + return soap->error; + } + if (soap->error == SOAP_STOP) + return soap->error; + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) + { soap->chunkbuflen = soap->buflen; + soap->buflen = soap->bufidx; + soap->chunksize = 0; + } +#ifndef WITH_LEANER + else if (soap->fpreparerecv && soap->buflen != soap->bufidx) + soap->fpreparerecv(soap, soap->buf + soap->bufidx, soap->buflen - soap->bufidx); +#endif + /* Note: fparse should not use soap_unget to push back last char */ + if (soap_get0(soap) == (int)EOF) + { if (soap->status == 200) + return soap->error = SOAP_NO_DATA; + return soap->error = soap->status; + } +#ifdef WITH_ZLIB + if (soap->zlib_in != SOAP_ZLIB_NONE) +#ifdef WITH_GZIP + { c = soap_get1(soap); + if (c == 0x1F) + { if (soap_getgziphdr(soap)) + return soap->error; + if (inflateInit2(&soap->d_stream, -MAX_WBITS) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; + soap->zlib_state = SOAP_ZLIB_INFLATE; + soap->z_crc = crc32(0L, NULL, 0); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n")); + } + else + { soap_revget1(soap); +#else + { +#endif + if (inflateInit(&soap->d_stream) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; + soap->zlib_state = SOAP_ZLIB_INFLATE; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate initialized\n")); + } + soap->mode |= SOAP_ENC_ZLIB; + memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); + soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx); + soap->d_stream.avail_in = soap->buflen - soap->bufidx; + soap->z_buflen = soap->buflen; + soap->buflen = soap->bufidx; + } +#endif + if (soap->error) + { if (soap->error == SOAP_FORM && soap->fform) + { soap->error = soap->fform(soap); + if (soap->error == SOAP_OK) + soap->error = SOAP_STOP; /* prevents further processing */ + } + return soap->error; + } + } +#endif +#ifndef WITH_LEANER + if (soap->mode & SOAP_ENC_MIME) + { if (soap_getmimehdr(soap)) + return soap->error; + if (soap->mime.start) + { do + { if (!soap->mime.last->id) + break; + if (!soap_match_cid(soap, soap->mime.start, soap->mime.last->id)) + break; + } while (soap_get_mime_attachment(soap, NULL)); + } + if (soap_get_header_attribute(soap, soap->mime.first->type, "application/dime")) + soap->mode |= SOAP_ENC_DIME; + } + if (soap->mode & SOAP_ENC_DIME) + { if (soap_getdimehdr(soap)) + return soap->error; + if (soap->dime.flags & SOAP_DIME_CF) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked DIME SOAP message\n")); + soap->dime.chunksize = soap->dime.size; + if (soap->buflen - soap->bufidx >= soap->dime.chunksize) + { soap->dime.buflen = soap->buflen; + soap->buflen = soap->bufidx + soap->dime.chunksize; + } + else + soap->dime.chunksize -= soap->buflen - soap->bufidx; + } + soap->count = soap->buflen - soap->bufidx; + } +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_parse(struct soap *soap) +{ char header[SOAP_HDRLEN], *s; + unsigned short get = 0, status = 0, k = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Waiting for HTTP request/response...\n")); + *soap->endpoint = '\0'; + soap->length = 0; + soap->userid = NULL; + soap->passwd = NULL; + soap->action = NULL; + soap->authrealm = NULL; + do + { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) + return soap->error; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP status: %s\n", soap->msgbuf)); + for (;;) + { if (soap_getline(soap, header, SOAP_HDRLEN)) + { if (soap->error == SOAP_EOF) + { soap->error = SOAP_OK; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "EOF in HTTP header, continue anyway\n")); + break; + } + return soap->error; + } + if (!*header) + break; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP header: %s\n", header)); + s = strchr(header, ':'); + if (s) + { *s = '\0'; + do s++; + while (*s && *s <= 32); + if ((soap->error = soap->fparsehdr(soap, header, s))) + { if (soap->error < SOAP_STOP) + return soap->error; + status = soap->error; + soap->error = SOAP_OK; + } + } + } + if ((s = strchr(soap->msgbuf, ' '))) + { k = (unsigned short)soap_strtoul(s, &s, 10); + if (!soap_blank(*s)) + k = 0; + } + else + k = 0; + } while (k == 100); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Finished HTTP header parsing, status = %d\n", k)); + s = strstr(soap->msgbuf, "HTTP/"); + if (s && s[7] != '1') + { if (soap->keep_alive == 1) + soap->keep_alive = 0; + if (k == 0 && (soap->omode & SOAP_IO) == SOAP_IO_CHUNK) /* k == 0 for HTTP request */ + { soap->imode |= SOAP_IO_CHUNK; + soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE; + } + } + if (soap->keep_alive < 0) + soap->keep_alive = 1; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Keep alive connection = %d\n", soap->keep_alive)); + if (s && (((get = !strncmp(soap->msgbuf, "GET ", 4))) || !strncmp(soap->msgbuf, "POST ", 5))) + { size_t m = strlen(soap->endpoint); + size_t n = m + (s - soap->msgbuf) - 5 - (!get); + if (m > n) + m = n; + if (n >= sizeof(soap->endpoint)) + n = sizeof(soap->endpoint) - 1; + strncpy(soap->path, soap->msgbuf + 4 + (!get), n - m); + soap->path[n - m] = '\0'; + strcat(soap->endpoint, soap->path); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Target endpoint='%s'\n", soap->endpoint)); + if (get) + { soap->error = soap->fget(soap); + if (soap->error == SOAP_OK) + soap->error = SOAP_STOP; /* prevents further processing */ + return soap->error; + } + if (status) + return soap->error = status; + } + soap->status = k; + if (k == 0 || k == 200 || (((k > 200 && k <= 299) || k == 400 || k == 500) && ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK || soap->length > 0))) + return SOAP_OK; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP error %d\n", k)); + return soap_set_receiver_error(soap, "HTTP Error", soap->msgbuf, k); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_parse_header(struct soap *soap, const char *key, const char *val) +{ if (!soap_tag_cmp(key, "Host")) + { +#ifdef WITH_OPENSSL + if (soap->imode & SOAP_ENC_SSL) + strcpy(soap->endpoint, "https://"); + else +#endif + strcpy(soap->endpoint, "http://"); + strncat(soap->endpoint, val, sizeof(soap->endpoint) - 8); + soap->endpoint[sizeof(soap->endpoint) - 1] = '\0'; + } +#ifndef WITH_LEANER + else if (!soap_tag_cmp(key, "Content-Type")) + { soap->http_content = soap_strdup(soap, val); + if (soap_get_header_attribute(soap, val, "application/dime")) + soap->mode |= SOAP_ENC_DIME; + else if (soap_get_header_attribute(soap, val, "multipart/related") + || soap_get_header_attribute(soap, val, "multipart/form-data")) + { soap->mime.boundary = soap_strdup(soap, soap_get_header_attribute(soap, val, "boundary")); + soap->mime.start = soap_strdup(soap, soap_get_header_attribute(soap, val, "start")); + soap->mode |= SOAP_ENC_MIME; + } + } +#endif + else if (!soap_tag_cmp(key, "Content-Length")) + soap->length = soap_strtoul(val, NULL, 10); + else if (!soap_tag_cmp(key, "Content-Encoding")) + { if (!soap_tag_cmp(val, "deflate")) +#ifdef WITH_ZLIB + soap->zlib_in = SOAP_ZLIB_DEFLATE; +#else + return SOAP_ZLIB_ERROR; +#endif + else if (!soap_tag_cmp(val, "gzip")) +#ifdef WITH_GZIP + soap->zlib_in = SOAP_ZLIB_GZIP; +#else + return SOAP_ZLIB_ERROR; +#endif + } +#ifdef WITH_ZLIB + else if (!soap_tag_cmp(key, "Accept-Encoding")) + { +#ifdef WITH_GZIP + if (strchr(val, '*') || soap_get_header_attribute(soap, val, "gzip")) + soap->zlib_out = SOAP_ZLIB_GZIP; + else +#endif + if (strchr(val, '*') || soap_get_header_attribute(soap, val, "deflate")) + soap->zlib_out = SOAP_ZLIB_DEFLATE; + else + soap->zlib_out = SOAP_ZLIB_NONE; + } +#endif + else if (!soap_tag_cmp(key, "Transfer-Encoding")) + { soap->mode &= ~SOAP_IO; + if (!soap_tag_cmp(val, "chunked")) + soap->mode |= SOAP_IO_CHUNK; + } + else if (!soap_tag_cmp(key, "Connection")) + { if (!soap_tag_cmp(val, "keep-alive")) + soap->keep_alive = -soap->keep_alive; + else if (!soap_tag_cmp(val, "close")) + soap->keep_alive = 0; + } +#ifndef WITH_LEAN + else if (!soap_tag_cmp(key, "Authorization")) + { if (!soap_tag_cmp(val, "Basic *")) + { int n; + char *s; + soap_base642s(soap, val + 6, soap->tmpbuf, sizeof(soap->tmpbuf) - 1, &n); + soap->tmpbuf[n] = '\0'; + if ((s = strchr(soap->tmpbuf, ':'))) + { *s = '\0'; + soap->userid = soap_strdup(soap, soap->tmpbuf); + soap->passwd = soap_strdup(soap, s + 1); + } + } + } + else if (!soap_tag_cmp(key, "WWW-Authenticate")) + soap->authrealm = soap_strdup(soap, soap_get_header_attribute(soap, val + 6, "realm")); + else if (!soap_tag_cmp(key, "Expect")) + { if (!soap_tag_cmp(val, "100-continue")) + { if ((soap->error = soap->fposthdr(soap, "HTTP/1.1 100 Continue", NULL)) + || (soap->error = soap->fposthdr(soap, NULL, NULL))) + return soap->error; + } + } +#endif + else if (!soap_tag_cmp(key, "SOAPAction")) + { if (*val == '"') + { soap->action = soap_strdup(soap, val + 1); + soap->action[strlen(soap->action) - 1] = '\0'; + } + } + else if (!soap_tag_cmp(key, "Location")) + { strncpy(soap->endpoint, val, sizeof(soap->endpoint)); + soap->endpoint[sizeof(soap->endpoint) - 1] = '\0'; + } +#ifdef WITH_COOKIES + else if (!soap_tag_cmp(key, "Cookie") + || !soap_tag_cmp(key, "Cookie2") + || !soap_tag_cmp(key, "Set-Cookie") + || !soap_tag_cmp(key, "Set-Cookie2")) + soap_getcookies(soap, val); +#endif + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_get_header_attribute(struct soap *soap, const char *line, const char *key) +{ register const char *s = line; + if (s) + { while (*s) + { register short flag; + s = soap_decode_key(soap->tmpbuf, sizeof(soap->tmpbuf), s); + flag = soap_tag_cmp(soap->tmpbuf, key); + s = soap_decode_val(soap->tmpbuf, sizeof(soap->tmpbuf), s); + if (!flag) + return soap->tmpbuf; + } + } + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_decode_key(char *buf, size_t len, const char *val) +{ return soap_decode(buf, len, val, "=,;"); +} +#endif +#endif + +/******************************************************************************/ +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_decode_val(char *buf, size_t len, const char *val) +{ if (*val != '=') + { *buf = '\0'; + return val; + } + return soap_decode(buf, len, val + 1, ",;"); +} +#endif +#endif + +/******************************************************************************/ +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +#ifndef PALM_1 +static const char* +soap_decode(char *buf, size_t len, const char *val, const char *sep) +{ const char *s; + char *t = buf; + for (s = val; *s; s++) + if (*s != ' ' && *s != '\t' && !strchr(sep, *s)) + break; + if (*s == '"') + { s++; + while (*s && *s != '"' && --len) + *t++ = *s++; + } + else + { while (soap_notblank(*s) && !strchr(sep, *s) && --len) + { if (*s == '%') + { *t++ = ((s[1] >= 'A' ? (s[1] & 0x7) + 9 : s[1] - '0') << 4) + + (s[2] >= 'A' ? (s[2] & 0x7) + 9 : s[2] - '0'); + s += 3; + } + else + *t++ = *s++; + } + } + *t = '\0'; + while (*s && !strchr(sep, *s)) + s++; + return s; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_envelope_begin_out(struct soap *soap) +{ +#ifndef WITH_LEANER + size_t n = 0; + if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && soap->mime.start && strlen(soap->mime.boundary) + strlen(soap->mime.start) < sizeof(soap->tmpbuf) - 80 ) + { const char *s; + if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) + s = "application/dime"; + else if (soap->version == 2) + { if (soap->mode & SOAP_ENC_MTOM) + s = "application/xop+xml; charset=utf-8; type=application/soap+xml"; + else + s = "application/soap+xml; charset=utf-8"; + } + else + s = "text/xml; charset=utf-8"; + sprintf(soap->tmpbuf, "--%s\r\nContent-Type: %s\r\nContent-Transfer-Encoding: binary\r\nContent-ID: %s\r\n\r\n", soap->mime.boundary, s, soap->mime.start); + n = strlen(soap->tmpbuf); + if (soap_send_raw(soap, soap->tmpbuf, n)) + return soap->error; + } + if (soap->mode & SOAP_IO_LENGTH) + soap->dime.size = soap->count; /* DIME in MIME correction */ + if (!(soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME)) + { if (soap_putdimehdr(soap)) + return soap->error; + } +#endif + soap->part = SOAP_IN_ENVELOPE; + return soap_element_begin_out(soap, "SOAP-ENV:Envelope", 0, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_envelope_end_out(struct soap *soap) +{ if (soap_element_end_out(soap, "SOAP-ENV:Envelope")) + return soap->error; +#ifndef WITH_LEANER + if ((soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) + { soap->dime.size = soap->count - soap->dime.size; /* DIME in MIME correction */ + sprintf(soap->id, soap->dime_id_format, 0); + soap->dime.id = soap->id; + if (soap->local_namespaces) + { if (soap->local_namespaces[0].out) + soap->dime.type = (char*)soap->local_namespaces[0].out; + else + soap->dime.type = (char*)soap->local_namespaces[0].ns; + } + soap->dime.options = NULL; + soap->dime.flags = SOAP_DIME_MB | SOAP_DIME_ABSURI; + if (!soap->dime.first) + soap->dime.flags |= SOAP_DIME_ME; + soap->count += 12 + ((strlen(soap->dime.id)+3)&(~3)) + (soap->dime.type ? ((strlen(soap->dime.type)+3)&(~3)) : 0); + } + if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) + return soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3); +#endif + soap->part = SOAP_END_ENVELOPE; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_envelope_begin_in(struct soap *soap) +{ register struct Namespace *p; + soap->part = SOAP_IN_ENVELOPE; + if (soap_element_begin_in(soap, "SOAP-ENV:Envelope", 0, NULL)) + { +#ifndef WITH_LEAN + if (!soap_element_begin_in(soap, "html", 0, NULL)) + { /* get HTML from buffer, stop receiving to avoid HTML parsing issues */ + char *s; +#ifndef WITH_NOIO + size_t (*f)(struct soap*, char*, size_t) = soap->frecv; + soap->frecv = frecv_stop; +#endif + soap_revert(soap); + s = soap_string_in(soap, 1, -1, -1); +#ifndef WITH_NOIO + soap->frecv = f; +#endif + return soap_set_receiver_error(soap, "HTTP Error", s, SOAP_HTTP_ERROR); + } +#endif + return soap->error = SOAP_VERSIONMISMATCH; + } + p = soap->local_namespaces; + if (p) + { const char *ns = p[0].out; + if (!ns) + ns = p[0].ns; + if (!strcmp(ns, soap_env1)) + { soap->version = 1; /* make sure we use SOAP 1.1 */ + if (p[1].out) + SOAP_FREE(soap, p[1].out); + if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc1)))) + strcpy(p[1].out, soap_enc1); + } + else if (!strcmp(ns, soap_env2)) + { soap->version = 2; /* make sure we use SOAP 1.2 */ + if (p[1].out) + SOAP_FREE(soap, p[1].out); + if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc2)))) + strcpy(p[1].out, soap_enc2); + } + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_envelope_end_in(struct soap *soap) +{ soap->part = SOAP_END_ENVELOPE; + return soap_element_end_in(soap, "SOAP-ENV:Envelope"); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_body_begin_out(struct soap *soap) +{ soap->part = SOAP_IN_BODY; + if (soap->version == 1) + soap->encoding = 1; +#ifndef WITH_LEAN + if ((soap->mode & SOAP_XML_SEC) && soap_set_attr(soap, "wsu:Id", "Body")) + return soap->error; +#endif + if (soap_element(soap, "SOAP-ENV:Body", 0, NULL)) + return soap->error; + return soap_element_start_end_out(soap, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_body_end_out(struct soap *soap) +{ if (soap_element_end_out(soap, "SOAP-ENV:Body")) + return soap->error; + soap->part = SOAP_END_BODY; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_body_begin_in(struct soap *soap) +{ soap->part = SOAP_IN_BODY; + if (soap_element_begin_in(soap, "SOAP-ENV:Body", 0, NULL)) + return soap->error; + if (!soap->body) + soap->part = SOAP_NO_BODY; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_body_end_in(struct soap *soap) +{ if (soap->part == SOAP_NO_BODY) + return SOAP_OK; + soap->part = SOAP_END_BODY; + return soap_element_end_in(soap, "SOAP-ENV:Body"); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv_header(struct soap *soap) +{ if (soap_getheader(soap) && soap->error == SOAP_TAG_MISMATCH) + soap->error = SOAP_OK; + else if (soap->error == SOAP_OK && soap->fheader) + soap->error = soap->fheader(soap); + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_endpoint(struct soap *soap, const char *endpoint) +{ register const char *s; + register size_t i, n; + soap->endpoint[0] = '\0'; + soap->host[0] = '\0'; + soap->path[0] = '/'; + soap->path[1] = '\0'; + soap->port = 80; + if (!endpoint || !*endpoint) + return; +#ifdef WITH_OPENSSL + if (!soap_tag_cmp(endpoint, "https:*")) + soap->port = 443; +#endif + strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint) - 1); + soap->endpoint[sizeof(soap->endpoint) - 1] = '\0'; + s = strchr(endpoint, ':'); + if (s && s[1] == '/' && s[2] == '/') + s += 3; + else + s = endpoint; + n = strlen(s); + if (n >= sizeof(soap->host)) + n = sizeof(soap->host) - 1; +#ifdef WITH_IPV6 + if (s[0] == '[') + { s++; + for (i = 0; i < n; i++) + { soap->host[i] = s[i]; + if (s[i] == ']') + { s++; + break; + } + } + } + else + { for (i = 0; i < n; i++) + { soap->host[i] = s[i]; + if (s[i] == '/' || s[i] == ':') + break; + } + } +#else + for (i = 0; i < n; i++) + { soap->host[i] = s[i]; + if (s[i] == '/' || s[i] == ':') + break; + } +#endif + soap->host[i] = '\0'; + if (s[i] == ':') + { soap->port = (int)atol(s + i + 1); + for (i++; i < n; i++) + if (s[i] == '/') + break; + } + if (s[i]) + { strncpy(soap->path, s + i, sizeof(soap->path)); + soap->path[sizeof(soap->path) - 1] = '\0'; + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_connect(struct soap *soap, const char *endpoint, const char *action) +{ return soap_connect_command(soap, SOAP_POST, endpoint, action); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_connect_command(struct soap *soap, int http_command, const char *endpoint, const char *action) +{ char host[sizeof(soap->host)]; + int port; + size_t count; + soap->error = SOAP_OK; + strcpy(host, soap->host); /* save to compare */ + port = soap->port; /* save to compare */ + soap_set_endpoint(soap, endpoint); +#ifndef WITH_LEANER + if (soap->fconnect) + { if ((soap->error = soap->fconnect(soap, endpoint, soap->host, soap->port))) + return soap->error; + } + else +#endif + if (soap->fopen && *soap->host) + { soap->status = http_command; + if (!soap->keep_alive || !soap_valid_socket(soap->socket) || strcmp(soap->host, host) || soap->port != port || !soap->fpoll || soap->fpoll(soap)) + { soap->keep_alive = 0; /* to force close */ + soap->omode &= ~SOAP_IO_UDP; /* to force close */ + soap_closesock(soap); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Connect/reconnect to host='%s' path='%s' port=%d\n", soap->host, soap->path, soap->port)); +#ifdef WITH_UDP + if (!strncmp(endpoint, "soap.udp:", 9)) + soap->omode |= SOAP_IO_UDP; +#endif + soap->socket = soap->fopen(soap, endpoint, soap->host, soap->port); + if (soap->error) + return soap->error; + soap->keep_alive = ((soap->omode & SOAP_IO_KEEPALIVE) != 0); + } + } + count = soap_count_attachments(soap); + if (soap_begin_send(soap)) + return soap->error; + if (http_command != SOAP_POST) + { soap->mode &= ~SOAP_IO; + soap->mode |= SOAP_IO_BUFFER; + } +#ifndef WITH_NOHTTP + soap->action = soap_strdup(soap, action); + if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML) && endpoint) + { unsigned int k = soap->mode; + soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB); + if ((k & SOAP_IO) != SOAP_IO_FLUSH) + soap->mode |= SOAP_IO_BUFFER; + if ((soap->error = soap->fpost(soap, endpoint, soap->host, soap->port, soap->path, action, count))) + return soap->error; +#ifndef WITH_LEANER + if ((k & SOAP_IO) == SOAP_IO_CHUNK) + { if (soap_flush(soap)) + return soap->error; + } +#endif + soap->mode = k; + } + if (http_command != SOAP_POST) + return soap_end_send(soap); +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_s2base64(struct soap *soap, const unsigned char *s, char *t, int n) +{ register int i; + register unsigned long m; + register char *p; + if (!t) + t = (char*)soap_malloc(soap, (n + 2) / 3 * 4 + 1); + if (!t) + { soap->error = SOAP_EOM; + return NULL; + } + p = t; + t[0] = '\0'; + if (!s) + return p; + for (; n > 2; n -= 3, s += 3) + { m = s[0]; + m = (m << 8) | s[1]; + m = (m << 8) | s[2]; + for (i = 4; i > 0; m >>= 6) + t[--i] = soap_base64o[m & 0x3F]; + t += 4; + } + t[0] = '\0'; + if (n > 0) + { m = 0; + for (i = 0; i < n; i++) + m = (m << 8) | *s++; + for (; i < 3; i++) + m <<= 8; + for (i++; i > 0; m >>= 6) + t[--i] = soap_base64o[m & 0x3F]; + for (i = 3; i > n; i--) + t[i] = '='; + t[4] = '\0'; + } + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_base642s(struct soap *soap, const char *s, char *t, size_t l, int *n) +{ register int i, j, c; + register unsigned long m; + register const char *p; + if (!s || !*s) + { if (n) + *n = 0; + if (soap->error) + return NULL; + return SOAP_NON_NULL; + } + if (!t) + { l = (strlen(s) + 3) / 4 * 3; + t = (char*)soap_malloc(soap, l); + } + if (!t) + { soap->error = SOAP_EOM; + return NULL; + } + p = t; + if (n) + *n = 0; + for (;;) + { for (i = 0; i < SOAP_BLKLEN; i++) + { m = 0; + j = 0; + while (j < 4) + { c = *s++; + if (c == '=' || !c) + { i *= 3; + switch (j) + { case 2: + *t++ = (char)((m >> 4) & 0xFF); + i++; + break; + case 3: + *t++ = (char)((m >> 10) & 0xFF); + *t++ = (char)((m >> 2) & 0xFF); + i += 2; + } + if (n) + *n += i; + return p; + } + c -= '+'; + if (c >= 0 && c <= 79) + { int b = soap_base64i[c]; + if (b >= 64) + { soap->error = SOAP_TYPE; + return NULL; + } + m = (m << 6) + b; + j++; + } + else if (!soap_blank(c + '+')) + { soap->error = SOAP_TYPE; + return NULL; + } + } + *t++ = (char)((m >> 16) & 0xFF); + *t++ = (char)((m >> 8) & 0xFF); + *t++ = (char)(m & 0xFF); + if (l < 3) + { if (n) + *n += i; + return p; + } + l -= 3; + } + if (n) + *n += 3 * SOAP_BLKLEN; + } +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_s2hex(struct soap *soap, const unsigned char *s, char *t, int n) +{ register char *p; + if (!t) + t = (char*)soap_malloc(soap, 2 * n + 1); + if (!t) + { soap->error = SOAP_EOM; + return NULL; + } + p = t; + t[0] = '\0'; + if (s) + { for (; n > 0; n--) + { register int m = *s++; + *t++ = (char)((m >> 4) + (m > 159 ? 'a' - 10 : '0')); + m &= 0x0F; + *t++ = (char)(m + (m > 9 ? 'a' - 10 : '0')); + } + } + *t++ = '\0'; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_hex2s(struct soap *soap, const char *s, char *t, size_t l, int *n) +{ register const char *p; + if (!s || !*s) + { if (n) + *n = 0; + if (soap->error) + return NULL; + return SOAP_NON_NULL; + } + if (!t) + { l = strlen(s) / 2; + t = (char*)soap_malloc(soap, l); + } + if (!t) + { soap->error = SOAP_EOM; + return NULL; + } + p = t; + while (l) + { register int d1, d2; + d1 = *s++; + if (!d1) + break; + d2 = *s++; + if (!d2) + break; + *t++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'); + l--; + } + if (n) + *n = t - p; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_puthttphdr(struct soap *soap, int status, size_t count) +{ if (soap->status != SOAP_GET) + { register const char *s = "text/xml; charset=utf-8"; + register int err = SOAP_OK; +#ifndef WITH_LEANER + register const char *r = NULL; +#endif + if (status == SOAP_FILE && soap->http_content) + s = soap->http_content; + else if (status == SOAP_HTML) + s = "text/html; charset=utf-8"; + else if (count || ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK)) + { if (soap->version == 2) + s = "application/soap+xml; charset=utf-8"; + } +#ifndef WITH_LEANER + if (soap->mode & (SOAP_ENC_DIME | SOAP_ENC_MTOM)) + { if (soap->mode & SOAP_ENC_MTOM) + { r = s; + s = "application/xop+xml; charset=utf-8"; + } + else + s = "application/dime"; + } + if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && strlen(soap->mime.boundary) + strlen(soap->mime.start ? soap->mime.start : SOAP_STR_EOS) < sizeof(soap->tmpbuf) - 80) + { register const char *t = strchr(s, ';'); + sprintf(soap->tmpbuf, "multipart/related; boundary=\"%s\"; type=\"", soap->mime.boundary); + if (t) + strncat(soap->tmpbuf, s, t - s); + else + strcat(soap->tmpbuf, s); + if (soap->mime.start) + { strcat(soap->tmpbuf, "\"; start=\""); + strcat(soap->tmpbuf, soap->mime.start); + } + strcat(soap->tmpbuf, "\""); + if (r) + { strcat(soap->tmpbuf, "; start-info=\""); + strcat(soap->tmpbuf, r); + strcat(soap->tmpbuf, "\""); + } + s = soap->tmpbuf; + } +#endif + if (s && (err = soap->fposthdr(soap, "Content-Type", s))) + return err; +#ifdef WITH_ZLIB + if (soap->omode & SOAP_ENC_ZLIB) + { err = soap->fposthdr(soap, "Content-Encoding", soap->zlib_out == SOAP_ZLIB_GZIP ? "gzip" : "deflate"); + if (err) + return err; + } +#endif +#ifndef WITH_LEANER + if ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK) + err = soap->fposthdr(soap, "Transfer-Encoding", "chunked"); + else +#endif + if (s) + { sprintf(soap->tmpbuf, "%lu", (unsigned long)count); + err = soap->fposthdr(soap, "Content-Length", soap->tmpbuf); + } + if (err) + return err; + } + return soap->fposthdr(soap, "Connection", soap->keep_alive ? "keep-alive" : "close"); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_get(struct soap *soap) +{ return SOAP_GET_METHOD; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_post(struct soap *soap, const char *endpoint, const char *host, int port, const char *path, const char *action, size_t count) +{ register const char *s; + register int err; + if (soap->status == SOAP_GET) + s = "GET"; + else + s = "POST"; +#ifdef PALM + if (!endpoint || (soap_tag_cmp(endpoint, "http:*") && soap_tag_cmp(endpoint, "https:*") && strncmp(endpoint, "httpg:", 6)) && strncmp(endpoint, "_beam:", 6) && strncmp(endpoint, "_local:", 7) && strncmp(endpoint, "_btobex:", 8)) +#else + if (!endpoint || (soap_tag_cmp(endpoint, "http:*") && soap_tag_cmp(endpoint, "https:*") && strncmp(endpoint, "httpg:", 6))) +#endif + return SOAP_OK; + if (strlen(endpoint) + strlen(soap->http_version) > sizeof(soap->tmpbuf) - 80) + return soap->error = SOAP_EOM; + if (soap->proxy_host && soap_tag_cmp(endpoint, "https:*")) + sprintf(soap->tmpbuf, "%s %s HTTP/%s", s, endpoint, soap->http_version); + else + sprintf(soap->tmpbuf, "%s /%s HTTP/%s", s, (*path == '/' ? path + 1 : path), soap->http_version); + if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return err; + if (port != 80) + sprintf(soap->tmpbuf, "%s:%d", host, port); + else + strcpy(soap->tmpbuf, host); + if ((err = soap->fposthdr(soap, "Host", soap->tmpbuf)) + || (err = soap->fposthdr(soap, "User-Agent", "gSOAP/2.7")) + || (err = soap_puthttphdr(soap, SOAP_OK, count))) + return err; +#ifdef WITH_ZLIB +#ifdef WITH_GZIP + if ((err = soap->fposthdr(soap, "Accept-Encoding", "gzip, deflate"))) +#else + if ((err = soap->fposthdr(soap, "Accept-Encoding", "deflate"))) +#endif + return err; +#endif +#ifndef WITH_LEAN + if (soap->userid && soap->passwd && strlen(soap->userid) + strlen(soap->passwd) < 761) + { sprintf(soap->tmpbuf + 262, "%s:%s", soap->userid, soap->passwd); + strcpy(soap->tmpbuf, "Basic "); + soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, strlen(soap->tmpbuf + 262)); + if ((err = soap->fposthdr(soap, "Authorization", soap->tmpbuf))) + return err; + } + if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761) + { sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd); + strcpy(soap->tmpbuf, "Basic "); + soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, strlen(soap->tmpbuf + 262)); + if ((err = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf))) + return err; + } +#endif +#ifdef WITH_COOKIES +#ifdef WITH_OPENSSL + if (soap_putcookies(soap, host, path, soap->ssl != NULL)) + return soap->error; +#else + if (soap_putcookies(soap, host, path, 0)) + return soap->error; +#endif +#endif + if (soap->status != SOAP_GET && (soap->version == 1 || (action && *action && strlen(action) < sizeof(soap->tmpbuf) - 2))) + { sprintf(soap->tmpbuf, "\"%s\"", action?action:""); + if ((err = soap->fposthdr(soap, "SOAPAction", soap->tmpbuf))) + return err; + } + return soap->fposthdr(soap, NULL, NULL); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_send_header(struct soap *soap, const char *s) +{ register const char *t; + do + { t = strchr(s, '\n'); /* disallow \n in HTTP headers */ + if (!t) + t = s + strlen(s); + if (soap_send_raw(soap, s, t - s)) + return soap->error; + s = t + 1; + } while (*t); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_post_header(struct soap *soap, const char *key, const char *val) +{ if (key) + { if (http_send_header(soap, key)) + return soap->error; + if (val && (soap_send_raw(soap, ": ", 2) || http_send_header(soap, val))) + return soap->error; + } + return soap_send_raw(soap, "\r\n", 2); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_response(struct soap *soap, int status, size_t count) +{ register int err; +#ifdef WMW_RPM_IO + if (soap->rpmreqid) + httpOutputEnable(soap->rpmreqid); +#endif + if (strlen(soap->http_version) > 4) + return soap->error = SOAP_EOM; + if (!status || status == SOAP_HTML || status == SOAP_FILE) + { const char *s; + if (count || ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK)) + s = "200 OK"; + else + s = "202 ACCEPTED"; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Status = %s\n", s)); +#ifdef WMW_RPM_IO + if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */ +#else + if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application */ +#endif + { sprintf(soap->tmpbuf, "HTTP/%s %s", soap->http_version, s); + if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return err; + } + else if ((err = soap->fposthdr(soap, "Status", s))) + return err; + } + else if (status >= 200 && status < 600) + { sprintf(soap->tmpbuf, "HTTP/%s %d %s", soap->http_version, status, http_error(soap, status)); + if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return err; +#ifndef WITH_LEAN + if (status == 401) + { sprintf(soap->tmpbuf, "Basic realm=\"%s\"", strlen(soap->authrealm) < sizeof(soap->tmpbuf) - 14 ? soap->authrealm : "gSOAP Web Service"); + if ((err = soap->fposthdr(soap, "WWW-Authenticate", soap->tmpbuf))) + return err; + } + else if ((status >= 301 && status <= 303) || status == 307) + { if ((err = soap->fposthdr(soap, "Location", soap->endpoint))) + return err; + } +#endif + } + else + { const char *s = *soap_faultcode(soap); + if (soap->version == 2 && !strcmp(s, "SOAP-ENV:Sender")) + s = "400 Bad Request"; + else + s = "500 Internal Server Error"; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error %s (status=%d)\n", s, status)); +#ifdef WMW_RPM_IO + if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */ +#else + if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application */ +#endif + { sprintf(soap->tmpbuf, "HTTP/%s %s", soap->http_version, s); + if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return err; + } + else if ((err = soap->fposthdr(soap, "Status", s))) /* CGI */ + return err; + } + if ((err = soap->fposthdr(soap, "Server", "gSOAP/2.7")) + || (err = soap_puthttphdr(soap, status, count))) + return err; +#ifdef WITH_COOKIES + if (soap_putsetcookies(soap)) + return soap->error; +#endif + return soap->fposthdr(soap, NULL, NULL); +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_response(struct soap *soap, int status) +{ register size_t count; + if (!(soap->omode & (SOAP_ENC_XML | SOAP_IO_STORE /* this tests for chunking too */)) + && (status == SOAP_HTML || status == SOAP_FILE)) + { soap->omode &= ~SOAP_IO; + soap->omode |= SOAP_IO_STORE; + } + soap->status = status; + count = soap_count_attachments(soap); + if (soap_begin_send(soap)) + return soap->error; +#ifndef WITH_NOHTTP + if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML)) + { register int n = soap->mode; + soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB); + if ((n & SOAP_IO) != SOAP_IO_FLUSH) + soap->mode |= SOAP_IO_BUFFER; + if ((soap->error = soap->fresponse(soap, status, count))) + return soap->error; +#ifndef WITH_LEANER + if ((n & SOAP_IO) == SOAP_IO_CHUNK) + { if (soap_flush(soap)) + return soap->error; + } +#endif + soap->mode = n; + } +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static const char* +soap_set_validation_fault(struct soap *soap, const char *s, const char *t) +{ if (*soap->tag) + sprintf(soap->msgbuf, "Validation constraint violation: %s%s in element <%s>", s, t?t:SOAP_STR_EOS, soap->tag); + else + sprintf(soap->msgbuf, "Validation constraint violation: %s%s", s, t?t:SOAP_STR_EOS); + return soap->msgbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_fault(struct soap *soap) +{ const char **c = soap_faultcode(soap); + const char **s = soap_faultstring(soap); + if (soap->fseterror) + soap->fseterror(soap, c, s); + if (!*c) + { if (soap->version == 2) + *c = "SOAP-ENV:Sender"; + else + *c = "SOAP-ENV:Client"; + } + if (*s) + return; + switch (soap->error) + { +#ifndef WITH_LEAN + case SOAP_CLI_FAULT: + *s = "Client fault"; + break; + case SOAP_SVR_FAULT: + *s = "Server fault"; + break; + case SOAP_TAG_MISMATCH: + *s = soap_set_validation_fault(soap, "tag name or namespace mismatch", NULL); + break; + case SOAP_TYPE: + *s = soap_set_validation_fault(soap, "data type mismatch ", soap->type); + break; + case SOAP_SYNTAX_ERROR: + *s = "Well-formedness violation"; + break; + case SOAP_NO_TAG: + *s = "No XML element tag"; + break; + case SOAP_MUSTUNDERSTAND: + *c = "SOAP-ENV:MustUnderstand"; + sprintf(soap->msgbuf, "The data in element '%s' must be understood but cannot be handled", soap->tag); + *s = soap->msgbuf; + break; + case SOAP_VERSIONMISMATCH: + *c = "SOAP-ENV:VersionMismatch"; + *s = "SOAP version mismatch or invalid SOAP message"; + break; + case SOAP_DATAENCODINGUNKNOWN: + *c = "SOAP-ENV:DataEncodingUnknown"; + *s = "Unsupported SOAP data encoding"; + break; + case SOAP_NAMESPACE: + *s = soap_set_validation_fault(soap, "namespace error", NULL); + break; + case SOAP_USER_ERROR: + *s = "User error"; + break; + case SOAP_FATAL_ERROR: + *s = "Fatal error"; + break; + case SOAP_NO_METHOD: + sprintf(soap->msgbuf, "Method '%s' not implemented: method name or namespace not recognized", soap->tag); + *s = soap->msgbuf; + break; + case SOAP_NO_DATA: + *s = "Data required for operation"; + break; + case SOAP_GET_METHOD: + *s = "HTTP GET method not implemented"; + break; + case SOAP_EOM: + *s = "Out of memory"; + break; + case SOAP_MOE: + *s = "Memory overflow or memory corruption error"; + break; + case SOAP_IOB: + *s = "Array index out of bounds"; + break; + case SOAP_NULL: + *s = soap_set_validation_fault(soap, "nil not allowed", NULL); + break; + case SOAP_DUPLICATE_ID: + *s = soap_set_validation_fault(soap, "multiple definitions of id ", soap->id); + if (soap->version == 2) + *soap_faultsubcode(soap) = "SOAP-ENC:DuplicateID"; + break; + case SOAP_MISSING_ID: + *s = soap_set_validation_fault(soap, "missing id for ref ", soap->id); + if (soap->version == 2) + *soap_faultsubcode(soap) = "SOAP-ENC:MissingID"; + break; + case SOAP_HREF: + *s = soap_set_validation_fault(soap, "incompatible object ref ", soap->id); + break; + case SOAP_FAULT: + break; +#ifndef WITH_NOIO + case SOAP_UDP_ERROR: + *s = "Message too large for UDP packet"; + break; + case SOAP_TCP_ERROR: + *s = tcp_error(soap); + break; +#endif + case SOAP_HTTP_ERROR: + *s = "An HTTP processing error occurred"; + break; + case SOAP_SSL_ERROR: +#ifdef WITH_OPENSSL + *s = "SSL error"; +#else + *s = "OpenSSL not installed: recompile with -DWITH_OPENSSL"; +#endif + break; + case SOAP_PLUGIN_ERROR: + *s = "Plugin registry error"; + break; + case SOAP_DIME_ERROR: + *s = "DIME format error"; + break; + case SOAP_DIME_HREF: + *s = "DIME href to missing attachment"; + break; + case SOAP_DIME_MISMATCH: + *s = "DIME version/transmission error"; + break; + case SOAP_DIME_END: + *s = "End of DIME error"; + break; + case SOAP_MIME_ERROR: + *s = "MIME format error"; + break; + case SOAP_MIME_HREF: + *s = "MIME href to missing attachment"; + break; + case SOAP_MIME_END: + *s = "End of MIME error"; + break; + case SOAP_ZLIB_ERROR: +#ifdef WITH_ZLIB + sprintf(soap->msgbuf, "Zlib/gzip error: '%s'", soap->d_stream.msg?soap->d_stream.msg:""); + *s = soap->msgbuf; +#else + *s = "Zlib/gzip not installed for (de)compression: recompile with -DWITH_GZIP"; +#endif + break; + case SOAP_REQUIRED: + *s = soap_set_validation_fault(soap, "missing required attribute", NULL); + break; + case SOAP_PROHIBITED: + *s = soap_set_validation_fault(soap, "prohibited attribute present", NULL); + break; + case SOAP_OCCURS: + *s = soap_set_validation_fault(soap, "min/maxOccurs violation", NULL); + break; + case SOAP_LENGTH: + *s = soap_set_validation_fault(soap, "content length violation", NULL); + break; + case SOAP_FD_EXCEEDED: + *s = "Maximum number of open connections was reached"; + break; + case SOAP_STOP: + *s = "Stopped: no response sent"; + break; +#endif + case SOAP_EOF: +#ifndef WITH_NOIO + strcpy(soap->msgbuf, soap_strerror(soap)); +#ifndef WITH_LEAN + if (strlen(soap->msgbuf) + 25 < sizeof(soap->msgbuf)) + { memmove(soap->msgbuf + 25, soap->msgbuf, strlen(soap->msgbuf) + 1); + memcpy(soap->msgbuf, "End of file or no input: ", 25); + } +#endif + *s = soap->msgbuf; + break; +#else + *s = "End of file or no input"; + break; +#endif + default: +#ifndef WITH_NOHTTP +#ifndef WITH_LEAN + if (soap->error > 200 && soap->error < 600) + { sprintf(soap->msgbuf, "HTTP Error: %d %s", soap->error, http_error(soap, soap->error)); + *s = soap->msgbuf; + } + else +#endif +#endif + { sprintf(soap->msgbuf, "Error %d", soap->error); + *s = soap->msgbuf; + } + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send_fault(struct soap *soap) +{ register int status = soap->error; + int r = 1; + if (status == SOAP_STOP) + return status; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Sending back fault struct for error code %d\n", soap->error)); + soap->keep_alive = 0; /* to terminate connection */ + soap_set_fault(soap); +#ifndef WITH_NOIO +#ifndef WITH_LEAN + if (soap_valid_socket(soap->socket)) + { struct timeval timeout; + fd_set rfd, sfd; + timeout.tv_sec = 0; + timeout.tv_usec = 0; + FD_ZERO(&rfd); + FD_ZERO(&sfd); + FD_SET((SOAP_SOCKET)soap->socket, &rfd); + FD_SET((SOAP_SOCKET)soap->socket, &sfd); + r = select((SOAP_SOCKET)(soap->socket + 1), &rfd, &sfd, NULL, &timeout); + if (r > 0) + { if (!FD_ISSET((SOAP_SOCKET)soap->socket, &sfd) + || (FD_ISSET((SOAP_SOCKET)soap->socket, &rfd) + && recv((SOAP_SOCKET)soap->socket, soap->tmpbuf, 1, MSG_PEEK) < 0)) + r = 0; + } + } +#endif +#endif + if ((status != SOAP_EOF || (!soap->recv_timeout && !soap->send_timeout)) && r > 0) + { soap->error = SOAP_OK; + soap_serializeheader(soap); + soap_serializefault(soap); + soap_begin_count(soap); + if (soap->mode & SOAP_IO_LENGTH) + { soap_envelope_begin_out(soap); + soap_putheader(soap); + soap_body_begin_out(soap); + soap_putfault(soap); + soap_body_end_out(soap); + soap_envelope_end_out(soap); + } + soap_end_count(soap); + if (soap_response(soap, status) + || soap_envelope_begin_out(soap) + || soap_putheader(soap) + || soap_body_begin_out(soap) + || soap_putfault(soap) + || soap_body_end_out(soap) + || soap_envelope_end_out(soap)) + return soap_closesock(soap); + soap_end_send(soap); + } + soap->error = status; + return soap_closesock(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv_fault(struct soap *soap) +{ register int status = soap->error; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Receiving SOAP Fault\n")); + soap->error = SOAP_OK; + if (soap_getfault(soap)) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Error: soap_get_soapfault() failed. Is this a SOAP message at all?\n")); + *soap_faultcode(soap) = (soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client"); + soap->error = status; + soap_set_fault(soap); + } + else + { register const char *s = *soap_faultcode(soap); + if (!soap_match_tag(soap, s, "SOAP-ENV:Server") || !soap_match_tag(soap, s, "SOAP-ENV:Receiver")) + status = SOAP_SVR_FAULT; + else if (!soap_match_tag(soap, s, "SOAP-ENV:Client") || !soap_match_tag(soap, s, "SOAP-ENV:Sender")) + status = SOAP_CLI_FAULT; + else if (!soap_match_tag(soap, s, "SOAP-ENV:MustUnderstand")) + status = SOAP_MUSTUNDERSTAND; + else if (!soap_match_tag(soap, s, "SOAP-ENV:VersionMismatch")) + status = SOAP_VERSIONMISMATCH; + else + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Fault code %s\n", s)); + status = SOAP_FAULT; + } + if (soap_body_end_in(soap) + || soap_envelope_end_in(soap) + || soap_end_recv(soap)) + return soap_closesock(soap); + soap->error = status; + } + return soap_closesock(soap); +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send_empty_response(struct soap *soap, int status) +{ register soap_mode m = soap->omode; + soap->count = 0; + if ((m & SOAP_IO) == SOAP_IO_CHUNK) + { soap->omode &= ~SOAP_IO_CHUNK; + soap->omode |= SOAP_IO_BUFFER; + } + if (soap_response(soap, status) || soap_end_send(soap)) + { soap->omode = m; + return soap_closesock(soap); + } + soap->omode = m; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv_empty_response(struct soap *soap) +{ if (soap_begin_recv(soap) || soap_end_recv(soap)) + { if (soap->error != 202) + return soap_closesock(soap); + soap->error = SOAP_OK; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static const char* +soap_strerror(struct soap *soap) +{ register int err = soap->errnum; + if (err) + { +#ifndef WIN32 + return strerror(err); +#else +#ifndef UNDER_CE + DWORD len; + *soap->msgbuf = '\0'; + len = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)soap->msgbuf, (DWORD)sizeof(soap->msgbuf), NULL); +#else + DWORD i, len; + *soap->msgbuf = '\0'; + len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0, (LPTSTR)soap->msgbuf, (DWORD)(sizeof(soap->msgbuf)/sizeof(TCHAR)), NULL); + for (i = 0; i <= len; i++) + { if (((TCHAR*)soap->msgbuf)[i] < 0x80) + soap->msgbuf[i] = (char)((TCHAR*)soap->msgbuf)[i]; + else + soap->msgbuf[i] = '?'; + } +#endif + return soap->msgbuf; +#endif + } + return "Operation interrupted or timed out"; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +static int +soap_set_error(struct soap *soap, const char *faultcode, const char *faultsubcode, const char *faultstring, const char *faultdetail, int soaperror) +{ *soap_faultcode(soap) = faultcode; + if (faultsubcode) + *soap_faultsubcode(soap) = faultsubcode; + *soap_faultstring(soap) = faultstring; + if (faultdetail && *faultdetail) + { register const char **s = soap_faultdetail(soap); + if (s) + *s = faultdetail; + } + return soap->error = soaperror; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_sender_error(struct soap *soap, const char *faultstring, const char *faultdetail, int soaperror) +{ return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", NULL, faultstring, faultdetail, soaperror); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_receiver_error(struct soap *soap, const char *faultstring, const char *faultdetail, int soaperror) +{ return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", NULL, faultstring, faultdetail, soaperror); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +static int +soap_copy_fault(struct soap *soap, const char *faultcode, const char *faultsubcode, const char *faultstring, const char *faultdetail) +{ char *r = NULL, *s = NULL, *t = NULL; + if (faultsubcode) + r = soap_strdup(soap, faultsubcode); + if (faultstring) + s = soap_strdup(soap, faultstring); + if (faultdetail) + t = soap_strdup(soap, faultdetail); + return soap_set_error(soap, faultcode, r, s, t, SOAP_FAULT); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_sender_fault(struct soap *soap, const char *faultstring, const char *faultdetail) +{ return soap_sender_fault_subcode(soap, NULL, faultstring, faultdetail); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_sender_fault_subcode(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail) +{ return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", faultsubcode, faultstring, faultdetail); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_receiver_fault(struct soap *soap, const char *faultstring, const char *faultdetail) +{ return soap_receiver_fault_subcode(soap, NULL, faultstring, faultdetail); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_receiver_fault_subcode(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail) +{ return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", faultsubcode, faultstring, faultdetail); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +#ifndef WITH_NOSTDLIB +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_print_fault(struct soap *soap, FILE *fd) +{ if (soap_check_state(soap)) + fprintf(fd, "Error: soap struct not initialized\n"); + else if (soap->error) + { const char *c, *v = NULL, *s, **d; + d = soap_faultcode(soap); + if (!*d) + soap_set_fault(soap); + c = *d; + if (soap->version == 2) + v = *soap_faultsubcode(soap); + s = *soap_faultstring(soap); + d = soap_faultdetail(soap); + fprintf(fd, "%s%d fault: %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, c, v ? v : "no subcode", s ? s : "[no reason]", d && *d ? *d : "[no detail]"); + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +#ifndef WITH_NOSTDLIB +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_print_fault_location(struct soap *soap, FILE *fd) +{ +#ifndef WITH_LEAN + int i, j, c1, c2; + if (soap->error && soap->bufidx <= soap->buflen && soap->buflen > 0 && soap->buflen <= SOAP_BUFLEN) + { i = (int)soap->bufidx - 1; + if (i <= 0) + i = 0; + c1 = soap->buf[i]; + soap->buf[i] = '\0'; + if ((int)soap->buflen >= i + 1024) + j = i + 1023; + else + j = (int)soap->buflen - 1; + c2 = soap->buf[j]; + soap->buf[j] = '\0'; + fprintf(fd, "%s%c\n\n", soap->buf, c1); + if (soap->bufidx < soap->buflen) + fprintf(fd, "%s\n", soap->buf + soap->bufidx); + soap->buf[i] = c1; + soap->buf[j] = c2; + } +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_register_plugin_arg(struct soap *soap, int (*fcreate)(struct soap*, struct soap_plugin*, void*), void *arg) +{ register struct soap_plugin *p; + register int r; + if (!(p = (struct soap_plugin*)SOAP_MALLOC(soap, sizeof(struct soap_plugin)))) + return soap->error = SOAP_EOM; + p->id = NULL; + p->data = NULL; + p->fcopy = NULL; + p->fdelete = NULL; + r = fcreate(soap, p, arg); + if (!r && p->fdelete) + { p->next = soap->plugins; + soap->plugins = p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Registered '%s' plugin\n", p->id)); + return SOAP_OK; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not register plugin '%s': plugin returned error %d (or fdelete callback not set)\n", p->id?p->id:"?", r)); + SOAP_FREE(soap, p); + return r; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static void * +fplugin(struct soap *soap, const char *id) +{ register struct soap_plugin *p; + for (p = soap->plugins; p; p = p->next) + if (p->id == id || !strcmp(p->id, id)) + return p->data; + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void * +SOAP_FMAC2 +soap_lookup_plugin(struct soap *soap, const char *id) +{ return soap->fplugin(soap, id); +} +#endif + +/******************************************************************************/ +#ifdef __cplusplus +} +#endif + +/******************************************************************************\ + * + * C++ soap struct methods + * +\******************************************************************************/ + +#ifdef __cplusplus +#ifndef WITH_LEAN +soap::soap() +{ soap_init(this); +} +#endif +#endif + +/******************************************************************************/ +#ifdef __cplusplus +#ifndef WITH_LEAN +soap::soap(soap_mode m) +{ soap_init1(this, m); +} +#endif +#endif + +/******************************************************************************/ +#ifdef __cplusplus +#ifndef WITH_LEAN +soap::soap(soap_mode im, soap_mode om) +{ soap_init2(this, im, om); +} +#endif +#endif + +/******************************************************************************/ +#ifdef __cplusplus +#ifndef WITH_LEAN +soap::soap(struct soap& soap) +{ soap_copy_context(this, &soap); +} +#endif +#endif + +/******************************************************************************/ +#ifdef __cplusplus +#ifndef WITH_LEAN +soap::~soap() +{ soap_destroy(this); + soap_end(this); + soap_done(this); +} +#endif +#endif + +/******************************************************************************/ diff --git a/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.9d.h b/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.9d.h new file mode 100644 index 0000000..44efa13 --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.9d.h @@ -0,0 +1,2184 @@ +/* + +stdsoap2.h 2.7.9d + +gSOAP runtime + +gSOAP XML Web services tools +Copyright (C) 2000-2007, Robert van Engelen, Genivia Inc., All Rights Reserved. +This part of the software is released under one of the following licenses: +GPL, the gSOAP public license, or Genivia's license for commercial use. +-------------------------------------------------------------------------------- +Contributors: + +Wind River Systems, Inc., for the following additions (marked WR[...]): + - vxWorks compatible +-------------------------------------------------------------------------------- +gSOAP public license. + +The contents of this file are subject to the gSOAP Public License Version 1.3 +(the "License"); you may not use this file except in compliance with the +License. You may obtain a copy of the License at +http://www.cs.fsu.edu/~engelen/soaplicense.html +Software distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +for the specific language governing rights and limitations under the License. + +The Initial Developer of the Original Code is Robert A. van Engelen. +Copyright (C) 2000-2007, Robert van Engelen, Genivia Inc., All Rights Reserved. +-------------------------------------------------------------------------------- +GPL license. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA + +Author contact information: +engelen@genivia.com / engelen@acm.org +-------------------------------------------------------------------------------- +A commercial use license is available from Genivia, Inc., contact@genivia.com +-------------------------------------------------------------------------------- +*/ + +#ifdef WITH_SOAPDEFS_H +# include "soapdefs.h" /* include user-defined stuff */ +#endif + +#ifndef _THREAD_SAFE +# define _THREAD_SAFE +#endif + +#ifndef OPENSERVER +# ifndef _REENTRANT +# define _REENTRANT +# endif +#endif + +#ifndef SOAP_FMAC1 /* stdsoap2.h declaration macro */ +# define SOAP_FMAC1 +#endif + +#ifndef SOAP_FMAC2 /* stdsoap2.h declaration macro */ +# define SOAP_FMAC2 +#endif + +#ifndef SOAP_FMAC3 /* (de)serializer declaration macro */ +# define SOAP_FMAC3 +#endif + +#ifndef SOAP_FMAC3S /* string converter for (de)serializer declaration macro */ +# define SOAP_FMAC3S SOAP_FMAC3 +#endif + +#ifndef SOAP_FMAC4 /* (de)serializer declaration macro */ +# define SOAP_FMAC4 +#endif + +#ifndef SOAP_FMAC4S /* string converter for (de)serializer declaration macro */ +# define SOAP_FMAC4S SOAP_FMAC4 +#endif + +#ifndef SOAP_FMAC5 /* stub/skeleton declaration macro */ +# define SOAP_FMAC5 +#endif + +#ifndef SOAP_FMAC6 /* stub/skeleton declaration macro */ +# define SOAP_FMAC6 +#endif + +#ifndef SOAP_CMAC /* class declaration macro */ +# define SOAP_CMAC +#endif + +#ifndef SOAP_NMAC /* namespace table declaration macro */ +# define SOAP_NMAC +#endif + +#ifndef SOAP_SOURCE_STAMP +# define SOAP_SOURCE_STAMP(str) +#endif + +/* gSOAP 2.7.4 and higher: fast look-aside buffering is stable */ +#ifndef WITH_FAST +# define WITH_FAST +#endif + +#ifdef WITH_LEANER +# ifndef WITH_LEAN +# define WITH_LEAN +# endif +#endif + +#ifdef WITH_LEAN +# ifdef WITH_COOKIES +# error "Cannot build WITH_LEAN code WITH_COOKIES enabled" +# endif +#endif + +#ifndef STDSOAP_H +#define STDSOAP_H + +#if defined(__vxworks) || defined(__VXWORKS__) +# define VXWORKS +#endif + +#ifdef _WIN32 +# ifndef WIN32 +# define WIN32 +# endif +#endif + +#ifdef _WIN32_WCE +# ifndef UNDER_CE +# define UNDER_CE _WIN32_WCE +# endif +#endif + +#ifdef UNDER_CE +# ifndef WIN32 +# define WIN32 +# endif +#endif + +#ifdef __BORLANDC__ +# ifdef __WIN32__ +# ifndef WIN32 +# define WIN32 +# endif +# endif +#endif + +#ifdef __CYGWIN__ +# ifndef CYGWIN +# define CYGWIN +# endif +#endif + +#ifdef __SYMBIAN32__ +# define SYMBIAN +# undef WIN32 +#endif + +#if defined(__palmos__) || defined(PALM_GCC) || defined(__PALMOS_TRAPS__) +# ifndef PALM +# define PALM +# endif +#endif + +#if defined(__hpux) +# ifndef HP_UX +# define HP_UX +# endif +#endif + +#if defined(__alpha) && !defined(__VMS) +# ifndef TRU64 +# define TRU64 +# endif +#endif + +#ifdef __MVS__ +# ifndef OS390 +# define OS390 +# endif +#endif + +#ifdef HAVE_CONFIG_H +# include "config.h" +# ifdef WITH_OPENSSL +# ifndef HAVE_OPENSSL_SSL_H +# undef WITH_OPENSSL +# endif +# endif +#else +# if defined(UNDER_CE) +# define WITH_LEAN +# define HAVE_SSCANF +# elif defined(WIN32) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# define SOAP_LONG_FORMAT "%I64d" +# define SOAP_ULONG_FORMAT "%I64u" +# elif defined(CYGWIN) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(__APPLE__) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_TIMEGM +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(_AIXVERSION_431) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(HP_UX) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(FREEBSD) || defined(__FreeBSD__) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_STRTOLL +# define HAVE_STRTOULL +# define HAVE_GETTIMEOFDAY +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# define SOAP_LONG_FORMAT "%qd" +# define SOAP_ULONG_FORMAT "%qu" +# elif defined(__VMS) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(__GLIBC__) || defined(__GNU__) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_STRTOLL +# define HAVE_STRTOULL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_TIMEGM +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# define HAVE_ISNAN +# elif defined(TRU64) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_GETTIMEOFDAY +# define HAVE_SYS_TIMEB_H +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define __USE_STD_IOSTREAM +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# define SOAP_LONG_FORMAT "%ld" +# define SOAP_ULONG_FORMAT "%lu" +# elif defined(MAC_CARBON) +# define WITH_NOIO +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GETHOSTBYNAME_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(PALM) +# define WITH_LEAN +# define HAVE_STRTOD /* strtod() is defined in palmFunctions.h */ +# include /* Needs to be included before unix headers */ +# include +# define IGNORE_STDIO_STUBS +# include +# define O_NONBLOCK FNONBIO +# include +# include "palmFunctions.h" +# elif defined(SYMBIAN) +# define WITH_LEAN +# define WITH_NONAMESPACES +# define HAVE_STRTOD /* use STRTOD since sscanf doesn't seem to work */ +# include +# include +# elif defined(VXWORKS) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_PGMTIME_R +# define HAVE_PLOCALTIME_R +# define HAVE_MKTIME +# elif defined(OS390) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(AS400) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(__QNX__) || defined(QNX) +/* QNX does not have a working version of strtof */ +# undef HAVE_STRTOF +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GETHOSTBYNAME_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# define LONG64 long +# define ULONG64 unsigned LONG64 +# define SOAP_LONG_FORMAT "%ld" +# define SOAP_ULONG_FORMAT "%lu" +# else +/* Default asumptions on supported functions */ +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GETHOSTBYNAME_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# endif +#endif + +#ifndef WITH_NOSTDLIB +# include +# ifndef PALM +# include +# include +# endif +# include +# include +#endif + +#if defined(__cplusplus) && !defined(WITH_LEAN) +# include +# include +#endif + +#ifdef WITH_NOHTTP +# ifndef WITH_NOIO +# define WITH_NOIO +# undef WITH_COOKIES +# endif +#endif + +#ifndef UNDER_CE +# ifndef PALM +# ifndef WITH_NOIO +# include +# include +# endif +# ifndef WITH_LEAN +# ifdef HAVE_SYS_TIMEB_H +# include /* for ftime() */ +# endif +# include +# endif +# endif +#endif + +#ifdef OPENSERVER +# include +# include +# include + extern int h_errno; +#endif + +#ifndef WITH_NOIO +# ifndef WIN32 +# ifndef PALM +# include +# ifdef VXWORKS +# include +# include +# endif +# ifndef VXWORKS +# ifndef SYMBIAN +# include +# endif +# endif +# ifdef SUN_OS +# include /* SUN */ +# include /* SUN < 2.8 (?) */ +# endif +# ifdef VXWORKS +# ifdef _WRS_KERNEL +# include +# endif +# else +# include +# endif +# include +# ifdef OS390 +# include +# else +# include /* TCP_NODELAY */ +# endif +# include +# endif +# endif +#endif + +#ifdef WITH_FASTCGI +# include +#endif + +#ifdef WITH_OPENSSL +# define OPENSSL_NO_KRB5 +# include +# include +# include +# include +# include +# ifndef ALLOW_OLD_VERSIONS +# if (OPENSSL_VERSION_NUMBER < 0x00905100L) +# error "Must use OpenSSL 0.9.6 or later" +# endif +# endif +#endif + +#ifdef WITH_GZIP +# ifndef WITH_ZLIB +# define WITH_ZLIB +# endif +#endif + +#ifdef WITH_CASEINSENSITIVETAGS +# define SOAP_STRCMP soap_tag_cmp /* case insensitve XML element/attribute names */ +#else +# define SOAP_STRCMP strcmp /* case sensitive XML element/attribute names */ +#endif + +#ifdef WITH_ZLIB +# include +#endif + +#ifndef WITH_NOSTDLIB +# ifndef PALM +# include /* for isnan() */ +# endif +#endif + +/* #define DEBUG */ /* Uncomment to debug sending (in file SENT.log) receiving (in file RECV.log) and messages (in file TEST.log) */ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef WIN32 +# ifndef UNDER_CE +# include +# include +# endif +# include +/* # include */ /* Alternative: use winsock2 (not available with eVC) */ +# ifdef WITH_IPV6 +# include +# include +# endif +#else +# ifdef VXWORKS +# include +# include +# include +# endif +# ifndef WITH_NOIO +# ifndef PALM +# include +# include +# include +# include +# endif +# endif +#endif + +/* Portability: define SOAP_SOCKLEN_T */ +#if defined(_AIX) +# define SOAP_SOCKLEN_T socklen_t +#elif defined(SOCKLEN_T) +# define SOAP_SOCKLEN_T SOCKLEN_T +#elif defined(__socklen_t_defined) || defined(_SOCKLEN_T) || defined(CYGWIN) || defined(FREEBSD) || defined(__FreeBSD__) || defined(__QNX__) || defined(QNX) +# define SOAP_SOCKLEN_T socklen_t +#elif defined(IRIX) || defined(WIN32) || defined(__APPLE__) || defined(HP_UX) || defined(SUN_OS) || defined(OPENSERVER) || defined(TRU64) || defined(VXWORKS) +# define SOAP_SOCKLEN_T int +#else +# define SOAP_SOCKLEN_T size_t +#endif + +#ifndef SOAP_SOCKET +# ifdef WIN32 +# define SOAP_SOCKET SOCKET +# define soap_closesocket(n) closesocket(n) +# else +# define SOAP_SOCKET int +# define soap_closesocket(n) close(n) +# endif +#endif + +#define SOAP_INVALID_SOCKET (-1) +#define soap_valid_socket(n) ((n) != SOAP_INVALID_SOCKET) + +#ifndef FD_SETSIZE +# define FD_SETSIZE (1024) +#endif + +#if defined(SYMBIAN) +# define LONG64 long +# define ULONG64 unsigned LONG64 +#elif !defined(WIN32) || defined(CYGWIN) || defined(__GLIBC__) || defined(__GNU__) +# ifndef LONG64 +# if defined(__GLIBC__) +# include +# if (__WORDSIZE == 64) +# define LONG64 int64_t +# define ULONG64 uint64_t +# ifndef SOAP_LONG_FORMAT +# define SOAP_LONG_FORMAT "%ld" +# endif +# ifndef SOAP_ULONG_FORMAT +# define SOAP_ULONG_FORMAT "%lu" +# endif +# else +# define LONG64 long long +# define ULONG64 unsigned LONG64 +# endif +# else +# define LONG64 long long +# define ULONG64 unsigned LONG64 +# endif +# endif +#elif defined(UNDER_CE) +# define LONG64 __int64 +# define ULONG64 unsigned LONG64 +#elif defined(__BORLANDC__) +# define LONG64 __int64 +# define ULONG64 unsigned LONG64 +#endif + +#ifndef SOAP_LONG_FORMAT +# define SOAP_LONG_FORMAT "%lld" /* printf format for 64 bit ints */ +#endif + +#ifndef SOAP_ULONG_FORMAT +# define SOAP_ULONG_FORMAT "%llu" /* printf format for unsigned 64 bit ints */ +#endif + +#if defined(WIN32) && !defined(CYGWIN) +# define soap_int32 __int32 +#elif defined(SYMBIAN) +# define soap_int32 long +#elif defined(PALM) +# define soap_int32 Int32 +#else +# define soap_int32 int32_t +#endif + +#ifdef WIN32 +# define SOAP_ERANGE ERANGE +# define SOAP_EINTR WSAEINTR +# define SOAP_EAGAIN WSAEWOULDBLOCK +# define SOAP_EWOULDBLOCK WSAEWOULDBLOCK +# define SOAP_EINPROGRESS WSAEINPROGRESS +# define SOAP_EADDRINUSE WSAEADDRINUSE +#else +# define SOAP_ERANGE ERANGE +# define SOAP_EINTR EINTR +# define SOAP_EAGAIN EAGAIN +# define SOAP_EADDRINUSE EADDRINUSE +# ifdef SYMBIAN +# define SOAP_EWOULDBLOCK 9898 +# define SOAP_EINPROGRESS 9899 +# else +# define SOAP_EWOULDBLOCK EWOULDBLOCK +# define SOAP_EINPROGRESS EINPROGRESS +# endif +#endif + +#ifdef WIN32 +# ifdef UNDER_CE +# define soap_errno GetLastError() +# define soap_socket_errno(s) GetLastError() +# define soap_reset_errno SetLastError(0) +# else +# define soap_errno GetLastError() +# define soap_socket_errno(s) WSAGetLastError() +# define soap_reset_errno SetLastError(0) +# endif +#else +# ifndef WITH_NOIO +# define soap_errno errno +# define soap_socket_errno(s) errno +# define soap_reset_errno (errno = 0) +# else +# define soap_errno 0 +# define soap_socket_errno(s) 0 +# define soap_reset_errno +# endif +#endif + +#ifndef SOAP_BUFLEN +# ifdef WITH_UDP +# define SOAP_BUFLEN (65536) /* max UDP packet size */ +# else +# ifndef WITH_LEAN +# define SOAP_BUFLEN (65536) /* buffer length for socket packets, also used by gethostbyname_r so don't make this too small */ +# else +# define SOAP_BUFLEN (2048) +# endif +# endif +#endif +#ifndef SOAP_LABLEN +# define SOAP_LABLEN (256) /* initial look-aside buffer length */ +#endif +#ifndef SOAP_PTRBLK +# define SOAP_PTRBLK (32) /* block allocation for pointer hash table chains */ +#endif +#ifndef SOAP_PTRHASH +# ifndef WITH_LEAN +# define SOAP_PTRHASH (1024) /* size of pointer analysis hash table (must be power of 2) */ +# else +# define SOAP_PTRHASH (32) +# endif +#endif +#ifndef SOAP_IDHASH +# ifndef WITH_LEAN +# define SOAP_IDHASH (1999) /* prime size of hash table for parsed id/ref */ +# else +# define SOAP_IDHASH (19) /* 19, 199 */ +# endif +#endif +#ifndef SOAP_BLKLEN +# ifndef WITH_LEAN +# define SOAP_BLKLEN (256) /* size of blocks to collect long strings and XML attributes */ +# else +# define SOAP_BLKLEN (32) +# endif +#endif +#ifndef SOAP_TAGLEN +# ifndef WITH_LEAN +# define SOAP_TAGLEN (1024) /* maximum length of XML element tag/attribute name or host/path name + 1 */ +# else +# define SOAP_TAGLEN (64) +# endif +#endif +#ifndef SOAP_HDRLEN +# ifndef WITH_LEAN +# define SOAP_HDRLEN (8192) /* maximum length of HTTP header line (must be >4096 to read cookies) */ +# else +# define SOAP_HDRLEN (1024) +# endif +#endif +#ifndef SOAP_MAXDIMS +# ifndef WITH_LEAN +# define SOAP_MAXDIMS (16) /* maximum array dimensions (array nestings) must be less than 64 to protect soap->tmpbuf */ +# else +# define SOAP_MAXDIMS (4) +# endif +#endif + +#ifndef SOAP_MAXLOGS +# define SOAP_MAXLOGS (3) /* max number of debug logs per struct soap environment */ +# define SOAP_INDEX_RECV (0) +# define SOAP_INDEX_SENT (1) +# define SOAP_INDEX_TEST (2) +#endif + +#ifndef SOAP_MAXKEEPALIVE +# define SOAP_MAXKEEPALIVE (100) /* max iterations to keep server connection alive */ +#endif + +#ifndef SOAP_MAXARRAYSIZE +# define SOAP_MAXARRAYSIZE (100000) /* "trusted" max size of inbound SOAP array for compound array allocation */ +#endif + +#ifdef VXWORKS +# ifdef __INCmathh +# include +# ifndef HAVE_ISNAN +# define HAVE_ISNAN +# endif +# define soap_isnan(num) isNan(num) +# endif +#endif + +#ifdef WIN32 +# include +# ifndef HAVE_ISNAN +# define HAVE_ISNAN +# endif +# define soap_isnan(num) _isnan(num) +#endif + +#ifdef SUN_OS +# define HAVE_ISNAN +#endif + +#ifdef __APPLE__ +# ifdef __cplusplus +# ifndef isnan +extern "C" int isnan(double); +# endif +# endif +# define HAVE_ISNAN +#endif + +#if !defined(HAVE_ISNAN) && (defined(_MATH_H) || defined(_MATH_INCLUDED)) +# define HAVE_ISNAN +#endif + +extern const struct soap_double_nan { unsigned int n1, n2; } soap_double_nan; + +#ifdef VXWORKS +# ifndef FLT_MAX +# define FLT_MAX _ARCH_FLT_MAX +# endif +# ifndef DBL_MAX +# define DBL_MAX _ARCH_DBL_MAX +# endif +#endif + +#ifndef FLT_NAN +# define FLT_NAN (*(float*)(void*)&soap_double_nan) +#endif + +#ifndef FLT_PINFTY +# if defined(FLT_MAX) +# define FLT_PINFTY FLT_MAX +# elif defined(HUGE_VALF) +# define FLT_PINFTY (float)HUGE_VALF +# elif defined(HUGE_VAL) +# define FLT_PINFTY (float)HUGE_VAL +# elif defined(FLOAT_MAX) +# define FLT_PINFTY FLOAT_MAX +# else +# define FLT_PINFTY (3.40282347e+38F) +# endif +#endif + +#ifndef FLT_NINFTY +# define FLT_NINFTY (-FLT_PINFTY) +#endif + +#ifndef DBL_NAN +# define DBL_NAN (*(double*)(void*)&soap_double_nan) +#endif + +#ifndef DBL_PINFTY +# if defined(DBL_MAX) +# define DBL_PINFTY DBL_MAX +# elif defined(HUGE_VALF) +# define DBL_PINFTY (double)HUGE_VALF +# elif defined(HUGE_VAL) +# define DBL_PINFTY (double)HUGE_VAL +# elif defined(DOUBLE_MAX) +# define DBL_PINFTY DOUBLE_MAX +# else +# define DBL_PINFTY (1.7976931348623157e+308) +# endif +#endif + +#ifndef DBL_NINFTY +# define DBL_NINFTY (-DBL_PINFTY) +#endif + +#ifndef soap_isnan +# ifdef HAVE_ISNAN +# define soap_isnan(n) isnan(n) +# else +# define soap_isnan(n) (0) +# endif +#endif + +#define soap_ispinfd(n) ((n) >= DBL_PINFTY) +#define soap_ispinff(n) ((n) >= FLT_PINFTY) +#define soap_isninfd(n) ((n) <= DBL_NINFTY) +#define soap_isninff(n) ((n) <= FLT_NINFTY) + +/* gSOAP error codes */ + +#define SOAP_EOF EOF +#define SOAP_ERR EOF +#define SOAP_OK 0 +#define SOAP_CLI_FAULT 1 +#define SOAP_SVR_FAULT 2 +#define SOAP_TAG_MISMATCH 3 +#define SOAP_TYPE 4 +#define SOAP_SYNTAX_ERROR 5 +#define SOAP_NO_TAG 6 +#define SOAP_IOB 7 +#define SOAP_MUSTUNDERSTAND 8 +#define SOAP_NAMESPACE 9 +#define SOAP_USER_ERROR 10 +#define SOAP_FATAL_ERROR 11 +#define SOAP_FAULT 12 +#define SOAP_NO_METHOD 13 +#define SOAP_NO_DATA 14 +#define SOAP_GET_METHOD 15 +#define SOAP_EOM 16 +#define SOAP_MOE 17 +#define SOAP_NULL 18 +#define SOAP_DUPLICATE_ID 19 +#define SOAP_MISSING_ID 20 +#define SOAP_HREF 21 +#define SOAP_UDP_ERROR 22 +#define SOAP_TCP_ERROR 23 +#define SOAP_HTTP_ERROR 24 +#define SOAP_SSL_ERROR 25 +#define SOAP_ZLIB_ERROR 26 +#define SOAP_DIME_ERROR 27 +#define SOAP_DIME_HREF 28 +#define SOAP_DIME_MISMATCH 29 +#define SOAP_DIME_END 30 +#define SOAP_MIME_ERROR 31 +#define SOAP_MIME_HREF 32 +#define SOAP_MIME_END 33 +#define SOAP_VERSIONMISMATCH 34 +#define SOAP_PLUGIN_ERROR 35 +#define SOAP_DATAENCODINGUNKNOWN 36 +#define SOAP_REQUIRED 37 +#define SOAP_PROHIBITED 38 +#define SOAP_OCCURS 39 +#define SOAP_LENGTH 40 +#define SOAP_FD_EXCEEDED 41 + +#define soap_xml_error_check(e) ((e) == SOAP_TAG_MISMATCH || (e) == SOAP_TAG_END || (e) == SOAP_SYNTAX_ERROR || (e) == SOAP_NAMESPACE || (e) == SOAP_DUPLICATE_ID || (e) == SOAP_MISSING_ID || (e) == SOAP_REQUIRED || (e) == SOAP_PROHIBITED || (e) == SOAP_OCCURS || (e) == SOAP_LENGTH || (e) == SOAP_NULL || (e) == SOAP_HREF) +#define soap_soap_error_check(e) ((e) == SOAP_CLI_FAULT || (e) == SOAP_SVR_FAULT || (e) == SOAP_VERSIONMISMATCH || (e) == SOAP_MUSTUNDERSTAND || (e) == SOAP_FAULT || (e) == SOAP_NO_METHOD) +#define soap_tcp_error_check(e) ((e) == SOAP_EOF || (e) == SOAP_TCP_ERROR) +#define soap_ssl_error_check(e) ((e) == SOAP_SSL_ERROR) +#define soap_zlib_error_check(e) ((e) == SOAP_ZLIB_ERROR) +#define soap_http_error_check(e) ((e) == SOAP_HTTP_ERROR || (e) == SOAP_GET_METHOD || (e) == SOAP_NO_DATA || ((e) >= 100 && (e) < 600)) + +/* gSOAP HTTP response status codes 100 to 599 are reserved */ + +/* Codes 600 to 999 are user definable */ + +/* Exceptional gSOAP HTTP response status codes >= 1000 */ + +#define SOAP_STOP 1000 /* No HTTP response */ +#define SOAP_FORM 1001 /* Form request/response */ +#define SOAP_HTML 1002 /* Custom HTML response */ +#define SOAP_FILE 1003 /* Custom file-based response */ + +/* gSOAP HTTP method codes */ + +#define SOAP_POST 2000 +#define SOAP_GET 2001 + +/* gSOAP DIME */ + +#define SOAP_DIME_CF 0x01 +#define SOAP_DIME_ME 0x02 +#define SOAP_DIME_MB 0x04 +#define SOAP_DIME_VERSION 0x08 /* DIME version 1 */ +#define SOAP_DIME_MEDIA 0x10 +#define SOAP_DIME_ABSURI 0x20 + +/* gSOAP ZLIB */ + +#define SOAP_ZLIB_NONE 0x00 +#define SOAP_ZLIB_DEFLATE 0x01 +#define SOAP_ZLIB_INFLATE 0x02 +#define SOAP_ZLIB_GZIP 0x02 + +/* gSOAP transport, connection, and content encoding modes */ + +typedef soap_int32 soap_mode; + +#define SOAP_IO 0x00000003 /* IO mask */ +#define SOAP_IO_FLUSH 0x00000000 /* flush output immediately, no buffering */ +#define SOAP_IO_BUFFER 0x00000001 /* buffer output in packets of size SOAP_BUFLEN */ +#define SOAP_IO_STORE 0x00000002 /* store entire output to determine length for transport */ +#define SOAP_IO_CHUNK 0x00000003 /* use HTTP chunked transfer AND buffer packets */ + +#define SOAP_IO_UDP 0x00000004 /* TCP or UDP */ + +#define SOAP_IO_LENGTH 0x00000008 /* calc message length (internal) */ +#define SOAP_IO_KEEPALIVE 0x00000010 /* keep connection alive */ + +#define SOAP_ENC_LATIN 0x00000020 /* accept iso-8859-1 encoding */ +#define SOAP_ENC_XML 0x00000040 /* plain XML encoding, no HTTP header */ +#define SOAP_ENC_DIME 0x00000080 +#define SOAP_ENC_MIME 0x00000100 +#define SOAP_ENC_MTOM 0x00000200 +#define SOAP_ENC_ZLIB 0x00000400 +#define SOAP_ENC_SSL 0x00000800 + +#define SOAP_ENC 0x00000FFF /* IO and ENC mask */ + +#define SOAP_XML_STRICT 0x00001000 /* apply strict validation */ +#define SOAP_XML_INDENT 0x00002000 /* emit indented XML */ +#define SOAP_XML_CANONICAL 0x00004000 /* EXC C14N canonical XML */ +#define SOAP_XML_TREE 0x00008000 /* emit XML tree (no id/ref) */ +#define SOAP_XML_GRAPH 0x00010000 +#define SOAP_XML_NIL 0x00020000 +#define SOAP_XML_DOM 0x00040000 +#define SOAP_XML_SEC 0x00080000 /* reserved for WS security */ + +#define SOAP_C_NOIOB 0x00100000 /* don't fault on array index out of bounds (just ignore) */ +#define SOAP_C_UTFSTRING 0x00200000 /* (de)serialize strings with UTF8 content */ +#define SOAP_C_MBSTRING 0x00400000 /* (de)serialize strings with multi-byte content */ +#define SOAP_C_NILSTRING 0x00800000 /* serialize empty strings as nil (omitted) */ + +#define SOAP_DOM_TREE 0x01000000 +#define SOAP_DOM_NODE 0x02000000 +#define SOAP_DOM_ASIS 0x04000000 + +#define SOAP_MIME_POSTCHECK 0x10000000 /* MIME flag (internal) */ + +#define SOAP_IO_DEFAULT SOAP_IO_FLUSH + +/* SSL client/server authentication settings */ + +#define SOAP_SSL_NO_AUTHENTICATION 0x00 /* for testing purposes */ +#define SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION 0x01 /* client requires server to authenticate */ +#define SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION 0x02 /* server requires client to authenticate */ +#define SOAP_SSL_SKIP_HOST_CHECK 0x04 /* client does not check the common name of the host in certificate */ +#define SOAP_SSL_RSA 0x08 /* use RSA */ +#define SOAP_SSLv3_TLSv1 0x00 /* SSL v3 and TLS v1 support by default */ +#define SOAP_SSLv3 0x10 /* SSL v3 only */ +#define SOAP_TLSv1 0x20 /* TLS v1 only */ + +#define SOAP_SSL_DEFAULT (SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION | SOAP_SSLv3_TLSv1) + +/* state */ + +#define SOAP_INIT 1 +#define SOAP_COPY 2 + +#define soap_check_state(soap) (!(soap) || ((soap)->state != SOAP_INIT && (soap)->state != SOAP_COPY)) + +/* part */ + +#define SOAP_BEGIN 0 +#define SOAP_IN_ENVELOPE 2 +#define SOAP_IN_HEADER 3 +#define SOAP_END_HEADER 4 +#define SOAP_NO_BODY 5 +#define SOAP_IN_BODY 6 +#define SOAP_END_BODY 7 +#define SOAP_END_ENVELOPE 8 +#define SOAP_END 9 +#define SOAP_BEGIN_SECURITY 10 +#define SOAP_IN_SECURITY 11 +#define SOAP_END_SECURITY 12 + +/* DEBUG macros */ + +#ifndef WITH_LEAN +# ifdef DEBUG +# ifndef SOAP_DEBUG +# define SOAP_DEBUG +# endif +# ifndef SOAP_MEM_DEBUG +# define SOAP_MEM_DEBUG +# endif +# endif +#endif + +#ifdef SOAP_MEM_DEBUG +# ifndef SOAP_MALLOC +# define SOAP_MALLOC(soap, size) soap_track_malloc(soap, __FILE__, __LINE__, size) +# endif +# ifndef SOAP_FREE +# define SOAP_FREE(soap, ptr) soap_track_free(soap, __FILE__, __LINE__, ptr) +# endif +#endif + +#ifndef SOAP_MALLOC /* use libc malloc */ +# define SOAP_MALLOC(soap, size) malloc(size) +#endif + +#ifndef SOAP_FREE /* use libc free */ +# define SOAP_FREE(soap, ptr) free(ptr) +#endif + +#ifdef SOAP_DEBUG +# ifndef SOAP_MESSAGE +# define SOAP_MESSAGE fprintf +# endif +# ifndef DBGLOG +# define DBGLOG(DBGFILE, CMD) \ +{ if (soap)\ + { if (!soap->fdebug[SOAP_INDEX_##DBGFILE])\ + soap_open_logfile((struct soap*)soap, SOAP_INDEX_##DBGFILE);\ + if (soap->fdebug[SOAP_INDEX_##DBGFILE])\ + { FILE *fdebug = soap->fdebug[SOAP_INDEX_##DBGFILE];\ + CMD;\ + fflush(fdebug);\ + }\ + }\ +} +# endif +# ifndef DBGMSG +# define DBGMSG(DBGFILE, MSG, LEN) \ +{ if (soap)\ + { if (!soap->fdebug[SOAP_INDEX_##DBGFILE])\ + soap_open_logfile((struct soap*)soap, SOAP_INDEX_##DBGFILE);\ + if (soap->fdebug[SOAP_INDEX_##DBGFILE])\ + { fwrite((MSG), 1, (LEN), soap->fdebug[SOAP_INDEX_##DBGFILE]);\ + fflush(soap->fdebug[SOAP_INDEX_##DBGFILE]);\ + }\ + }\ +} +# endif +# ifndef DGBFUN +# define DBGFUN(FNAME) DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): %s()\n", __FILE__, __LINE__, FNAME)) +# define DBGFUN1(FNAME, FMT, ARG) DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): %s("FMT")\n", __FILE__, __LINE__, FNAME, (ARG))) +# define DBGFUN2(FNAME, FMT1, ARG1, FMT2, ARG2) DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): %s("FMT1", "FMT2")\n", __FILE__, __LINE__, FNAME, (ARG1), (ARG2))) +# define DBGFUN3(FNAME, FMT1, ARG1, FMT2, ARG2, FMT3, ARG3) DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): %s("FMT1", "FMT2", "FMT3")\n", __FILE__, __LINE__, FNAME, (ARG1), (ARG2), (ARG3))) +# endif +# ifndef DBGHEX +# define DBGHEX(DBGFILE, MSG, LEN) \ +{ if (soap)\ + { if (!soap->fdebug[SOAP_INDEX_##DBGFILE])\ + soap_open_logfile(soap, SOAP_INDEX_##DBGFILE);\ + if (soap->fdebug[SOAP_INDEX_##DBGFILE])\ + { int i; char *s;\ + for (s = (char*)(MSG), i = (LEN); i; i--)\ + fprintf(soap->fdebug[SOAP_INDEX_##DBGFILE], "%2.2X ", (int)*s++&0xFF);\ + fflush(soap->fdebug[SOAP_INDEX_##DBGFILE]);\ + }\ + }\ +} +# endif +#else +# define DBGLOG(DBGFILE, CMD) +# define DBGMSG(DBGFILE, MSG, LEN) +# define DBGFUN(FNAME) +# define DBGFUN1(FNAME, FMT, ARG) +# define DBGFUN2(FNAME, FMT1, ARG1, FMT2, ARG2) +# define DBGFUN3(FNAME, FMT1, ARG1, FMT2, ARG2, FMT3, ARG3) +# define DBGHEX(DBGFILE, MSG, LEN) +#endif + +/* UCS-4 requires 32 bits (0-7FFFFFFF, the sign bit is used by gSOAP to distinguish XML entities) */ +typedef soap_int32 soap_wchar; + +/* namespace table row */ +struct Namespace +{ const char *id; + const char *ns; + const char *in; + char *out; +}; + +/* namespace stack */ +struct soap_nlist +{ struct soap_nlist *next; + unsigned int level; /* nesting depth level */ + short index; /* corresponding entry in ns mapping table */ + char *ns; /* only set when parsed ns URI is not in the ns mapping table */ + char id[1]; /* the actual string value flows into the allocated region below this struct */ +}; + +/* block stack for nested block allocations */ +struct soap_blist +{ struct soap_blist *next; + char *ptr; + size_t size; +}; + +/* array layout */ +struct soap_array +{ void *__ptr; + int __size; +}; + +/* pointer serialization management */ +struct soap_plist +{ struct soap_plist *next; + const void *ptr; + const struct soap_array *array; + int type; + int id; + char mark1; + char mark2; +}; + +/* block allocation for pointer serialization management */ +struct soap_pblk +{ struct soap_pblk *next; + struct soap_plist plist[SOAP_PTRBLK]; +}; + +#ifdef SOAP_MEM_DEBUG +/* malloc/free tracking for debugging */ +struct soap_mlist +{ struct soap_mlist *next; + const void *ptr; + const char *file; + int line; + short live; +}; +#endif + +/* class allocation list */ +struct soap_clist +{ struct soap_clist *next; + void *ptr; + int type; + int size; + int (*fdelete)(struct soap_clist*); +}; + +/* attributes */ +struct soap_attribute +{ struct soap_attribute *next; + char *value; + size_t size; + char *ns; + short visible; + char name[1]; /* the actual name string flows into the allocated region below this struct */ +}; + +#ifndef WITH_LEAN +struct soap_cookie +{ struct soap_cookie *next; + char *name; + char *value; + char *domain; + char *path; + time_t expire; /* client-side: local time to expire */ + long maxage; /* server-side: seconds to expire */ + unsigned int version; + short secure; + short session; /* server-side */ + short env; /* server-side: got cookie from client and should not be (re)send */ + short modified; /* server-side: client cookie was modified and should be send */ +}; +#endif + +#ifdef __cplusplus +SOAP_FMAC1 struct soap_multipart* SOAP_FMAC2 soap_next_multipart(struct soap_multipart*); + +class soap_multipart_iterator +{ public: + struct soap_multipart *content; + bool operator==(const soap_multipart_iterator& iter) const + { return content == iter.content; } + bool operator!=(const soap_multipart_iterator& iter) const + { return content != iter.content; } + struct soap_multipart &operator*() const + { return *content; } + soap_multipart_iterator &operator++() + { content = soap_next_multipart(content); return *this; } + soap_multipart_iterator() : content(NULL) + { } + soap_multipart_iterator(struct soap_multipart *p) : content(p) + { } +}; +#endif + +#ifndef WITH_LEANER +struct soap_dime +{ size_t count; + size_t size; + size_t chunksize; + size_t buflen; + char flags; + char *ptr; + const char *id; + const char *type; + const char *options; + struct soap_multipart *list; /* list of DIME attachments received */ + struct soap_multipart *first, *last; /* temporary in/out queue */ +#ifdef __cplusplus + soap_multipart_iterator begin() + { soap_multipart_iterator iter(list); return iter; }; + soap_multipart_iterator end() + { soap_multipart_iterator iter(NULL); return iter; }; +#endif +}; +#endif + +#ifndef WITH_LEANER +struct soap_mime +{ char *boundary; /* MIME boundary */ + const char *start; /* MIME start ID */ + struct soap_multipart *list; /* list of MIME attachments received */ + struct soap_multipart *first, *last; /* temporary in/out queue */ +#ifdef __cplusplus + soap_multipart_iterator begin() + { soap_multipart_iterator iter(list); return iter; }; + soap_multipart_iterator end() + { soap_multipart_iterator iter(NULL); return iter; }; +#endif +}; +#endif + +#ifndef WITH_LEANER +/* RFC2045 MIME content transfer encodings */ +enum soap_mime_encoding +{ SOAP_MIME_NONE, + SOAP_MIME_7BIT, + SOAP_MIME_8BIT, + SOAP_MIME_BINARY, + SOAP_MIME_QUOTED_PRINTABLE, + SOAP_MIME_BASE64, + SOAP_MIME_IETF_TOKEN, + SOAP_MIME_X_TOKEN +}; +#endif + +#ifndef WITH_LEANER +/* DIME/MIME multipart list */ +struct soap_multipart +{ struct soap_multipart *next; + char *ptr; /* points to raw data content */ + size_t size; /* size of data content */ + const char *id; /* DIME/MIME content ID or form data name */ + const char *type; /* DIME/MIME type (MIME type format) */ + const char *options; /* DIME options */ + enum soap_mime_encoding encoding; /* MIME Content-Transfer-Encoding */ + const char *location; /* MIME Content-Location (optional) */ + const char *description; /* MIME Content-Description (optional) */ +#ifdef __cplusplus + typedef soap_multipart_iterator iterator; +#endif +}; +#endif + +#ifndef WITH_LEANER +/* attachment DIME and MTOM XOP forwarding */ +struct soap_xlist +{ struct soap_xlist *next; + unsigned char **ptr; + int *size; + char *id; + char **type; + char **options; +}; +#endif + +/******************************************************************************/ + +#ifndef WITH_LEANER +#ifdef __cplusplus +class soap_dom_attribute_iterator +{ public: + struct soap_dom_attribute *att; + const char *nstr; + const char *name; + bool operator==(const soap_dom_attribute_iterator&) const; + bool operator!=(const soap_dom_attribute_iterator&) const; + struct soap_dom_attribute &operator*() const; + soap_dom_attribute_iterator &operator++(); + soap_dom_attribute_iterator(); + soap_dom_attribute_iterator(struct soap_dom_attribute*); + ~soap_dom_attribute_iterator(); +}; +#endif +#endif + +#ifndef WITH_LEANER +struct soap_dom_attribute +{ struct soap_dom_attribute *next; + const char *nstr; + char *name; + char *data; + wchar_t *wide; + struct soap *soap; +#ifdef __cplusplus + typedef soap_dom_attribute_iterator iterator; + struct soap_dom_attribute &set(const char *nstr, const char *name); /* set namespace and name */ + struct soap_dom_attribute &set(const char *data); /* set data */ + soap_dom_attribute_iterator begin(); + soap_dom_attribute_iterator end(); + soap_dom_attribute_iterator find(const char *nstr, const char *name); + void unlink(); + soap_dom_attribute(); + soap_dom_attribute(struct soap *soap); + soap_dom_attribute(struct soap *soap, const char *nstr, const char *name, const char *data); + ~soap_dom_attribute(); +#endif +}; +#endif + +#ifndef WITH_LEANER +#ifdef __cplusplus +class soap_dom_element_iterator +{ public: + struct soap_dom_element *elt; + const char *nstr; + const char *name; + int type; + bool operator==(const soap_dom_element_iterator&) const; + bool operator!=(const soap_dom_element_iterator&) const; + struct soap_dom_element &operator*() const; + soap_dom_element_iterator &operator++(); + soap_dom_element_iterator(); + soap_dom_element_iterator(struct soap_dom_element*); + ~soap_dom_element_iterator(); +}; +#endif +#endif + +#ifndef WITH_LEANER +struct soap_dom_element +{ struct soap_dom_element *next; /* next sibling */ + struct soap_dom_element *prnt; /* parent */ + struct soap_dom_element *elts; /* list of child elements */ + struct soap_dom_attribute *atts; /* list of attributes */ + const char *nstr; /* namespace string */ + char *name; /* element tag name */ + char *data; /* element content data (with SOAP_C_UTFSTRING flag set) */ + wchar_t *wide; /* element content data */ + int type; /* optional: serialized C/C++ data type */ + void *node; /* optional: pointer to serialized C/C++ data */ + char *head; /* leading whitespace to start tag */ + char *tail; /* leading whitespace to end tag */ + struct soap *soap; /* soap context that manages this node */ +#ifdef __cplusplus + typedef soap_dom_element_iterator iterator; + struct soap_dom_element &set(const char *nstr, const char *name); + struct soap_dom_element &set(const char *data); + struct soap_dom_element &set(void *node, int type); + struct soap_dom_element &add(struct soap_dom_element*); + struct soap_dom_element &add(struct soap_dom_element&); + struct soap_dom_element &add(struct soap_dom_attribute*); + struct soap_dom_element &add(struct soap_dom_attribute&); + soap_dom_element_iterator begin(); + soap_dom_element_iterator end(); + soap_dom_element_iterator find(const char *nstr, const char *name); + soap_dom_element_iterator find(int type); + void unlink(); + soap_dom_element(); + soap_dom_element(struct soap *soap); + soap_dom_element(struct soap *soap, const char *nstr, const char *name); + soap_dom_element(struct soap *soap, const char *nstr, const char *name, const char *data); + soap_dom_element(struct soap *soap, const char *nstr, const char *name, void *node, int type); + ~soap_dom_element(); +#endif +}; +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_dom_next_element(struct soap_dom_element *elt); +SOAP_FMAC1 struct soap_dom_attribute * SOAP_FMAC2 soap_dom_next_attribute(struct soap_dom_attribute *att); +#endif + +#if defined(__cplusplus) && !defined(WITH_LEAN) +} +extern std::ostream &operator<<(std::ostream&, const struct soap_dom_element&); +extern std::istream &operator>>(std::istream&, struct soap_dom_element&); +extern "C" { +#endif + +/******************************************************************************/ + +#ifdef WIN32 +# ifdef SOAP_STD_EXPORTS +# define SOAP_STD_API __declspec(dllexport) +# else +# define SOAP_STD_API +# endif +#else +# define SOAP_STD_API +#endif + +struct SOAP_STD_API soap +{ short state; /* 0 = uninitialized, 1 = initialized, 2 = copy of another soap struct */ + short version; /* 1 = SOAP1.1 and 2 = SOAP1.2 (set automatically from namespace URI in nsmap table) */ + soap_mode mode; + soap_mode imode; + soap_mode omode; + const char *float_format; /* user-definable format string for floats (<1024 chars) */ + const char *double_format; /* user-definable format string for doubles (<1024 chars) */ + const char *dime_id_format; /* user-definable format string for integer DIME id ( 0, gives socket recv timeout in seconds, < 0 in usec */ + int send_timeout; /* when > 0, gives socket send timeout in seconds, < 0 in usec */ + int connect_timeout; /* when > 0, gives socket connect() timeout in seconds, < 0 in usec */ + int accept_timeout; /* when > 0, gives socket accept() timeout in seconds, < 0 in usec */ + int socket_flags; /* socket recv() and send() flags, e.g. set to MSG_NOSIGNAL to disable sigpipe */ + int connect_flags; /* connect() SOL_SOCKET sockopt flags, e.g. set to SO_DEBUG to debug socket */ + int bind_flags; /* bind() SOL_SOCKET sockopt flags, e.g. set to SO_REUSEADDR to enable reuse */ + int accept_flags; /* accept() SOL_SOCKET sockopt flags */ + const struct Namespace *namespaces; /* Pointer to global namespace mapping table */ + struct Namespace *local_namespaces; /* Local namespace mapping table */ + struct soap_nlist *nlist; /* namespace stack */ + struct soap_blist *blist; /* block allocation stack */ + struct soap_clist *clist; /* class instance allocation list */ + void *alist; /* memory allocation (malloc) list */ + struct soap_ilist *iht[SOAP_IDHASH]; + struct soap_plist *pht[SOAP_PTRHASH]; + struct soap_pblk *pblk; /* plist block allocation */ + short pidx; /* plist block allocation */ + struct SOAP_ENV__Header *header; + struct SOAP_ENV__Fault *fault; + int idnum; + void *user; /* to pass user-defined data */ + struct soap_plugin *plugins; /* linked list of plug-in data */ + char *userid; /* HTTP Basic authorization userid */ + char *passwd; /* HTTP Basic authorization passwd */ + int (*fpost)(struct soap*, const char*, const char*, int, const char*, const char*, size_t); + int (*fget)(struct soap*); + int (*fform)(struct soap*); + int (*fposthdr)(struct soap*, const char*, const char*); + int (*fresponse)(struct soap*, int, size_t); + int (*fparse)(struct soap*); + int (*fparsehdr)(struct soap*, const char*, const char*); + int (*fheader)(struct soap*); + int (*fresolve)(struct soap*, const char*, struct in_addr* inaddr); + int (*fconnect)(struct soap*, const char*, const char*, int); + int (*fdisconnect)(struct soap*); + int (*fclosesocket)(struct soap*, SOAP_SOCKET); + int (*fshutdownsocket)(struct soap*, SOAP_SOCKET, int); + int (*fopen)(struct soap*, const char*, const char*, int); + int (*faccept)(struct soap*, int, struct sockaddr*, int *n); + int (*fclose)(struct soap*); + int (*fsend)(struct soap*, const char*, size_t); + size_t (*frecv)(struct soap*, char*, size_t); + int (*fpoll)(struct soap*); + void (*fseterror)(struct soap*, const char **c, const char **s); + int (*fignore)(struct soap*, const char*); + int (*fserveloop)(struct soap*); + void *(*fplugin)(struct soap*, const char*); + void *(*fmalloc)(struct soap*, size_t); +#ifndef WITH_LEANER + int (*fprepareinit)(struct soap*); + int (*fpreparesend)(struct soap*, const char*, size_t); + int (*fpreparerecv)(struct soap*, const char*, size_t); + int (*fpreparefinal)(struct soap*); + void *(*fdimereadopen)(struct soap*, void*, const char*, const char*, const char*); + void *(*fdimewriteopen)(struct soap*, const char*, const char*, const char*); + void (*fdimereadclose)(struct soap*, void*); + void (*fdimewriteclose)(struct soap*, void*); + size_t (*fdimeread)(struct soap*, void*, char*, size_t); + int (*fdimewrite)(struct soap*, void*, const char*, size_t); + void *(*fmimereadopen)(struct soap*, void*, const char*, const char*, const char*); + void *(*fmimewriteopen)(struct soap*, void*, const char*, const char*, const char*, enum soap_mime_encoding); + void (*fmimereadclose)(struct soap*, void*); + void (*fmimewriteclose)(struct soap*, void*); + size_t (*fmimeread)(struct soap*, void*, char*, size_t); + int (*fmimewrite)(struct soap*, void*, const char*, size_t); +#endif + int master; + int socket; +#if defined(__cplusplus) && !defined(WITH_LEAN) + std::ostream *os; + std::istream *is; +#else + void *os; /* preserve alignment */ + void *is; /* preserve alignment */ +#endif +#ifndef UNDER_CE + int sendfd; + int recvfd; +#else + FILE *sendfd; + FILE *recvfd; +#endif + size_t bufidx; /* index in soap.buf[] */ + size_t buflen; /* length of soap.buf[] content */ + soap_wchar ahead; /* parser lookahead */ + short cdata; /* CDATA parser state */ + short body; /* parsed XML element has a body or not */ + unsigned int level; /* XML nesting level */ + size_t count; /* message length counter */ + size_t length; /* message length as set by HTTP header */ + char *labbuf; /* look-aside buffer */ + size_t lablen; /* look-aside buffer allocated length */ + size_t labidx; /* look-aside buffer index to available part */ + char buf[SOAP_BUFLEN];/* send and receive buffer */ + char msgbuf[1024]; /* in/output buffer for messages >=1024 bytes */ + char tmpbuf[1024]; /* in/output buffer for HTTP/MIME headers, simpleType values, attribute names, and DIME must be >=1024 bytes */ + char tag[SOAP_TAGLEN]; + char id[SOAP_TAGLEN]; + char href[SOAP_TAGLEN]; + char type[SOAP_TAGLEN]; + char arrayType[SOAP_TAGLEN]; + char arraySize[SOAP_TAGLEN]; + char arrayOffset[SOAP_TAGLEN]; + short other; + short position; + int positions[SOAP_MAXDIMS]; + short root; + struct soap_attribute *attributes; /* attribute list */ + short encoding; /* when set, output encodingStyle */ + short mustUnderstand; /* a mustUnderstand element was parsed or is output */ + short keep_alive; /* connection should be kept open */ + short null; /* parsed XML is xsi:nil */ + short ns; /* when not set, output full xmlns bindings */ + short part; /* parsing state */ + short alloced; + short peeked; + size_t chunksize; + size_t chunkbuflen; + char endpoint[SOAP_TAGLEN]; + char path[SOAP_TAGLEN]; + char host[SOAP_TAGLEN]; + char *action; + char *authrealm; /* HTTP authentication realm */ + char *prolog; /* XML declaration prolog */ + unsigned long ip; /* IP number */ + int port; /* port number */ + unsigned int max_keep_alive; + const char *proxy_http_version;/* HTTP version of proxy "1.0" or "1.1" */ + const char *proxy_host; /* Proxy Server host name */ + int proxy_port; /* Proxy Server port (default = 8080) */ + const char *proxy_userid; /* Proxy Authorization user name */ + const char *proxy_passwd; /* Proxy Authorization password */ + int status; /* -1 when request, else error code to be returned by server */ + int error; + int errmode; + int errnum; +#ifndef WITH_LEANER + struct soap_dom_element *dom; + struct soap_dime dime; + struct soap_mime mime; + struct soap_xlist *xlist; +#endif +#if !defined(WITH_LEAN) || defined(SOAP_DEBUG) + const char *logfile[SOAP_MAXLOGS]; + FILE *fdebug[SOAP_MAXLOGS]; + struct soap_mlist *mht[SOAP_PTRHASH]; +#endif +#ifndef WITH_LEAN + const char *c14ninclude; + const char *c14nexclude; + struct soap_cookie *cookies; + const char *cookie_domain; + const char *cookie_path; + int cookie_max; +#endif +#ifndef WITH_NOIO +#ifdef WITH_IPV6 + struct sockaddr_storage peer; /* IPv6: set by soap_accept and by UDP recv */ +#else + struct sockaddr_in peer; /* IPv4: set by soap_connect/soap_accept and by UDP recv */ +#endif +#endif + size_t peerlen; +#ifdef WITH_OPENSSL + int (*fsslauth)(struct soap*); + int (*fsslverify)(int, X509_STORE_CTX*); + BIO *bio; + SSL *ssl; + SSL_CTX *ctx; + unsigned short ssl_flags; + const char *keyfile; + const char *password; + const char *dhfile; + const char *cafile; + const char *capath; + const char *crlfile; + const char *randfile; + SSL_SESSION *session; + char session_host[SOAP_TAGLEN]; + int session_port; +#endif +#ifdef WITH_ZLIB + short zlib_state; /* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_INFLATE */ + short zlib_in; /* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_GZIP */ + short zlib_out; /* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_GZIP */ + z_stream d_stream; /* decompression stream */ + char z_buf[SOAP_BUFLEN]; /* buffer */ + size_t z_buflen; + unsigned short z_level; /* compression level to be used (0=none, 1=fast to 9=best) */ + uLong z_crc; /* internal gzip crc */ + float z_ratio_in; /* detected compression ratio compressed_length/length of inbound message */ + float z_ratio_out; /* detected compression ratio compressed_length/length of outbound message */ +#endif +#ifdef WMW_RPM_IO + void *rpmreqid; +#endif +#ifndef WITH_LEAN +#ifdef __cplusplus + soap(); + soap(soap_mode); + soap(soap_mode, soap_mode); + soap(struct soap&); + ~soap(); +#endif +#endif +}; + +struct soap_code_map +{ long code; + const char *string; +}; + +/* forwarding list */ +struct soap_flist +{ struct soap_flist *next; + int type; + void *ptr; + unsigned int level; + size_t len; + void (*fcopy)(struct soap*, int, int, void*, size_t, const void*, size_t); +}; + +/* id-ref forwarding list */ +struct soap_ilist +{ struct soap_ilist *next; + int type; + size_t size; + void *link; + void *copy; + struct soap_flist *flist; + void *ptr; + unsigned int level; + char id[1]; /* the actual id string value flows into the allocated region below this struct */ +}; + +struct soap_plugin +{ struct soap_plugin *next; + const char *id; + void *data; + int (*fcopy)(struct soap *soap, struct soap_plugin *dst, struct soap_plugin *src); + void (*fdelete)(struct soap *soap, struct soap_plugin *p); /* should delete fields of plugin only and not free(p) */ +}; + +#ifndef WITH_NONAMESPACES +extern SOAP_NMAC struct Namespace namespaces[]; +#endif + +#ifndef WITH_LEAN +# define soap_get0(soap) (((soap)->bufidx>=(soap)->buflen && soap_recv(soap)) ? EOF : (unsigned char)(soap)->buf[(soap)->bufidx]) +# define soap_get1(soap) (((soap)->bufidx>=(soap)->buflen && soap_recv(soap)) ? EOF : (unsigned char)(soap)->buf[(soap)->bufidx++]) +#else +soap_wchar soap_get0(struct soap*); +soap_wchar soap_get1(struct soap*); +#endif + +#define soap_revget1(soap) ((soap)->bufidx--) +#define soap_unget(soap, c) ((soap)->ahead = c) +#define soap_register_plugin(soap, plugin) soap_register_plugin_arg(soap, plugin, NULL) +#define soap_imode(soap, n) ((soap)->mode = (soap)->imode = (n)) +#define soap_set_imode(soap, n) ((soap)->imode |= (n)) +#define soap_clr_imode(soap, n) ((soap)->imode &= ~(n)) +#define soap_omode(soap, n) ((soap)->mode = (soap)->omode = (n)) +#define soap_set_omode(soap, n) ((soap)->omode |= (n)) +#define soap_clr_omode(soap, n) ((soap)->omode &= ~(n)) +#define soap_set_mode(soap, n) ((soap)->imode |= (n), (soap)->omode |= (n)) +#define soap_clr_mode(soap, n) ((soap)->imode &= ~(n), (soap)->omode &= ~(n)) +#define soap_destroy(soap) soap_delete((soap), NULL) + +#ifdef HAVE_STRRCHR +# define soap_strrchr(s, t) strrchr(s, t) +#else + SOAP_FMAC1 char* SOAP_FMAC2 soap_strrchr(const char *s, int t); +#endif + +#ifdef HAVE_STRTOL +# define soap_strtol(s, t, b) strtol(s, t, b) +#else + SOAP_FMAC1 long SOAP_FMAC2 soap_strtol(const char *s, char **t, int b); +#endif + +#ifdef HAVE_STRTOUL +# define soap_strtoul(s, t, b) strtoul(s, t, b) +#else + SOAP_FMAC1 unsigned long SOAP_FMAC2 soap_strtoul(const char *s, char **t, int b); +#endif + +#if defined(WITH_OPENSSL) +# define soap_random soap_rand() +SOAP_FMAC1 int SOAP_FMAC2 soap_rand(void); +#elif defined(HAVE_RANDOM) +# define soap_random (int)random() +#else +# define soap_random rand() +#endif + +#ifdef WITH_NOIDREF +# define soap_embedded(s, p, t) (0) +# define soap_id_lookup(s, i, p, t, n, k) (p) +# define soap_id_forward(s, h, p, len, st, tt, n, k, fc) (p) +# define soap_reference(s, a, t) (1) +# define soap_array_reference(s, p, a, n, t) (1) +# define soap_embed(s, p, a, n, t, pp) (0) +# define soap_embedded_id(s, i, p, t) (i) +# define soap_is_embedded(s, p) (0) +# define soap_is_single(s, p) (1) +# define soap_lookup_type(s, i) (0) +# define soap_getindependent(s) (0) +# define soap_putindependent(s) (0) +# define soap_getelement(s, n) (n) +# define soap_putelement(s, p, t, i, n) (0) +# define soap_markelement(s, p, n) (0) +#endif + +SOAP_FMAC1 void SOAP_FMAC2 soap_fault(struct soap*); +SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultcode(struct soap*); +SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultsubcode(struct soap*); +SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultstring(struct soap*); +SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultdetail(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_serializeheader(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putheader(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getheader(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_serializefault(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putfault(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getfault(struct soap*); + +SOAP_FMAC1 void SOAP_FMAC2 soap_ssl_init(void); +SOAP_FMAC1 int SOAP_FMAC2 soap_poll(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_connect_command(struct soap*, int, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_connect(struct soap*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_bind(struct soap*, const char*, int, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_accept(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_accept(struct soap*); +SOAP_FMAC1 const char * SOAP_FMAC2 soap_ssl_error(struct soap*, int); + +SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_server_context(struct soap*, unsigned short, const char*, const char*, const char*, const char*, const char*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_client_context(struct soap*, unsigned short, const char*, const char*, const char*, const char*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_puthttphdr(struct soap*, int status, size_t count); + +SOAP_FMAC1 const char* SOAP_FMAC2 soap_get_header_attribute(struct soap*, const char*, const char*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_decode_key(char*, size_t, const char*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_decode_val(char*, size_t, const char*); + +SOAP_FMAC1 size_t SOAP_FMAC2 soap_hash(const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_endpoint(struct soap*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_flush_raw(struct soap*, const char*, size_t); +SOAP_FMAC1 int SOAP_FMAC2 soap_flush(struct soap*); +SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_get(struct soap*); +SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_getchar(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_tag_cmp(const char*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_fault(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_sender_fault(struct soap*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_sender_fault_subcode(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_receiver_fault(struct soap*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_receiver_fault_subcode(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_sender_error(struct soap*, const char*, const char*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_receiver_error(struct soap*, const char*, const char*, int); + +SOAP_FMAC1 int SOAP_FMAC2 soap_send_raw(struct soap*, const char*, size_t); +SOAP_FMAC1 int SOAP_FMAC2 soap_recv_raw(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_recv(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_send(struct soap*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_send2(struct soap*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_send3(struct soap*, const char*, const char*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_pututf8(struct soap*, unsigned long); +SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_getutf8(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_putbase64(struct soap*, const unsigned char*, int); +SOAP_FMAC1 unsigned char* SOAP_FMAC2 soap_getbase64(struct soap*, int*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_puthex(struct soap*, const unsigned char*, int); +SOAP_FMAC1 unsigned char* SOAP_FMAC2 soap_gethex(struct soap*, int*); + +#ifndef WITH_LEANER +SOAP_FMAC1 int SOAP_FMAC2 soap_xop_forward(struct soap*, unsigned char**, int*, char**, char**, char**); +SOAP_FMAC1 int SOAP_FMAC2 soap_dime_forward(struct soap*, unsigned char**, int*, char**, char**, char**); +#endif + +#ifndef WITH_NOIDREF +SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_lookup_id(struct soap*, void *p, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_lookup(struct soap*, const void *p, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_enter(struct soap*, const void *p, const struct soap_array *a, int n, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_array_pointer_lookup(struct soap*, const void *p, const struct soap_array *a, int n, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_embed(struct soap *soap, const void *p, const struct soap_array *a, int n, const char *tag, int type); +SOAP_FMAC1 struct soap_ilist* SOAP_FMAC2 soap_lookup(struct soap*, const char*); +SOAP_FMAC1 struct soap_ilist* SOAP_FMAC2 soap_enter(struct soap*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_resolve(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_embedded(struct soap*, const void *p, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_reference(struct soap*, const void *p, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_array_reference(struct soap*, const void *p, const struct soap_array *a, int n, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_embedded_id(struct soap*, int id, const void *p, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_is_embedded(struct soap*, struct soap_plist*); +SOAP_FMAC1 int SOAP_FMAC2 soap_is_single(struct soap*, struct soap_plist*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_embedded(struct soap*, struct soap_plist*); +#endif + +SOAP_FMAC1 int SOAP_FMAC2 soap_begin_count(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_end_count(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_begin_send(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_end_send(struct soap*); + +SOAP_FMAC1 const struct soap_code_map* SOAP_FMAC2 soap_code(const struct soap_code_map*, const char*); +SOAP_FMAC1 long SOAP_FMAC2 soap_code_int(const struct soap_code_map*, const char*, long); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_code_str(const struct soap_code_map*, long); +SOAP_FMAC1 long SOAP_FMAC2 soap_code_bits(const struct soap_code_map*, const char*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_code_list(struct soap*, const struct soap_code_map*, long); + +SOAP_FMAC1 int SOAP_FMAC2 soap_getline(struct soap*, char*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_begin_recv(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_end_recv(struct soap*); + +SOAP_FMAC1 void* SOAP_FMAC2 soap_malloc(struct soap*, size_t); +SOAP_FMAC1 void SOAP_FMAC2 soap_dealloc(struct soap*, void*); +SOAP_FMAC1 struct soap_clist * SOAP_FMAC2 soap_link(struct soap*, void*, int, int, int (*fdelete)(struct soap_clist*)); +SOAP_FMAC1 void SOAP_FMAC2 soap_unlink(struct soap*, const void*); +SOAP_FMAC1 void SOAP_FMAC2 soap_free_temp(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_del(struct soap*); + +SOAP_FMAC1 void* SOAP_FMAC2 soap_track_malloc(struct soap*, const char*, int, size_t); +SOAP_FMAC1 void SOAP_FMAC2 soap_track_free(struct soap*, const char*, int, void*); + +#ifndef WITH_NOIDREF +SOAP_FMAC1 int SOAP_FMAC2 soap_lookup_type(struct soap*, const char *id); +SOAP_FMAC1 void* SOAP_FMAC2 soap_id_lookup(struct soap*, const char *id, void **p, int t, size_t n, unsigned int k); +SOAP_FMAC1 void* SOAP_FMAC2 soap_id_forward(struct soap*, const char *id, void *p, size_t len, int st, int tt, size_t n, unsigned int k, void(*fcopy)(struct soap*, int, int, void*, size_t, const void*, size_t)); +#endif +SOAP_FMAC1 void* SOAP_FMAC2 soap_id_enter(struct soap*, const char *id, void *p, int t, size_t n, unsigned int k, const char *type, const char *arrayType, void *(*finstantiate)(struct soap*, int, const char*, const char*, size_t*)); +SOAP_FMAC1 void SOAP_FMAC2 soap_fcopy(struct soap *soap, int st, int tt, void *p, size_t, const void *q, size_t n); + +SOAP_FMAC1 int SOAP_FMAC2 soap_size(const int *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_getoffsets(const char *, const int *, int *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_getsize(const char *, const char *, int *); +SOAP_FMAC1 int SOAP_FMAC2 soap_getsizes(const char *, int *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_getposition(const char *, int *); + +SOAP_FMAC1 char* SOAP_FMAC2 soap_putsize(struct soap*, const char *, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_putsizesoffsets(struct soap*, const char *, const int *, const int *, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_putsizes(struct soap*, const char *, const int *, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_putoffset(struct soap*, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_putoffsets(struct soap*, const int *, int); + +SOAP_FMAC1 int SOAP_FMAC2 soap_closesock(struct soap*); + +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_new(void); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_new1(soap_mode); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_new2(soap_mode, soap_mode); +SOAP_FMAC1 void SOAP_FMAC2 soap_free(struct soap*); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_copy(struct soap*); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_copy_context(struct soap*, struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_copy_stream(struct soap*, struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_init(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_init1(struct soap*, soap_mode); +SOAP_FMAC1 void SOAP_FMAC2 soap_init2(struct soap*, soap_mode, soap_mode); +SOAP_FMAC1 void SOAP_FMAC2 soap_done(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_cleanup(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_begin(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_end(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_delete(struct soap*, void*); + +#ifdef SOAP_DEBUG +SOAP_FMAC1 void SOAP_FMAC2 soap_set_recv_logfile(struct soap*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_sent_logfile(struct soap*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_test_logfile(struct soap*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_close_logfiles(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_open_logfile(struct soap*, int); +#endif + +SOAP_FMAC1 const char* SOAP_FMAC2 soap_value(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_match_tag(struct soap*, const char*, const char *); +SOAP_FMAC1 int SOAP_FMAC2 soap_match_array(struct soap*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_element(struct soap*, const char*, int, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_begin_out(struct soap*, const char *tag, int id, const char *type); +SOAP_FMAC1 int SOAP_FMAC2 soap_array_begin_out(struct soap*, const char *tag, int id, const char *type, const char *offset); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_ref(struct soap*, const char *tag, int id, int href); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_href(struct soap*, const char *tag, int id, const char *ref, const char *val); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_null(struct soap*, const char *tag, int id, const char *type); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_id(struct soap*, const char *tag, int id, const void *p, const struct soap_array *a, int d, const char *type, int n); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_result(struct soap*, const char *tag); +SOAP_FMAC1 void SOAP_FMAC2 soap_check_result(struct soap*, const char *tag); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_end_out(struct soap*, const char *tag); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_start_end_out(struct soap*, const char *tag); + +SOAP_FMAC1 int SOAP_FMAC2 soap_attribute(struct soap*, const char*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_element_begin_in(struct soap*, const char *tag, int nillable, const char *type); + +SOAP_FMAC1 int SOAP_FMAC2 soap_element_end_in(struct soap*, const char *tag); + +SOAP_FMAC1 int SOAP_FMAC2 soap_peek_element(struct soap*); + +SOAP_FMAC1 void SOAP_FMAC2 soap_retry(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_revert(struct soap*); + +SOAP_FMAC1 char* SOAP_FMAC2 soap_strdup(struct soap*, const char*); +SOAP_FMAC1 const char * SOAP_FMAC2 soap_strsearch(const char *big, const char *little); + +SOAP_FMAC1 int SOAP_FMAC2 soap_string_out(struct soap*, const char *s, int flag); +SOAP_FMAC1 char* SOAP_FMAC2 soap_string_in(struct soap*, int, long, long); + +#ifndef WITH_LEANER +SOAP_FMAC1 int SOAP_FMAC2 soap_wstring_out(struct soap*, const wchar_t *s, int flag); +SOAP_FMAC1 wchar_t* SOAP_FMAC2 soap_wstring_in(struct soap*, int, long, long); +#endif + +SOAP_FMAC1 int SOAP_FMAC2 soap_match_namespace(struct soap*, const char *, const char*, int n1, int n2); + +SOAP_FMAC1 int SOAP_FMAC2 soap_set_namespaces(struct soap*, const struct Namespace*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_local_namespaces(struct soap*); + +SOAP_FMAC1 void SOAP_FMAC2 soap_pop_namespace(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_push_namespace(struct soap*, const char *,const char *); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_current_namespace(struct soap *soap, const char *tag); + +SOAP_FMAC1 struct soap_nlist* SOAP_FMAC2 soap_lookup_ns(struct soap *soap, const char *tag, size_t n); + +SOAP_FMAC1 int SOAP_FMAC2 soap_store_lab(struct soap*, const char*, size_t); +SOAP_FMAC1 int SOAP_FMAC2 soap_append_lab(struct soap*, const char*, size_t); + +SOAP_FMAC1 int SOAP_FMAC2 soap_new_block(struct soap*); +SOAP_FMAC1 void* SOAP_FMAC2 soap_push_block(struct soap*, size_t); +SOAP_FMAC1 void SOAP_FMAC2 soap_pop_block(struct soap*); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_size_block(struct soap*, size_t); +SOAP_FMAC1 char* SOAP_FMAC2 soap_first_block(struct soap*); +SOAP_FMAC1 char* SOAP_FMAC2 soap_next_block(struct soap*); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_block_size(struct soap*); +SOAP_FMAC1 char* SOAP_FMAC2 soap_save_block(struct soap*, char*, int); +SOAP_FMAC1 void SOAP_FMAC2 soap_end_block(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_begin_out(struct soap*); +SOAP_FMAC1 int soap_envelope_end_out(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_begin_in(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_end_in(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_body_begin_out(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_body_end_out(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_body_begin_in(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_body_end_in(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_recv_header(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_response(struct soap*, int); + +SOAP_FMAC1 int SOAP_FMAC2 soap_send_empty_response(struct soap*, int status); +SOAP_FMAC1 int SOAP_FMAC2 soap_recv_empty_response(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_send_fault(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_recv_fault(struct soap*); + +#ifndef WITH_NOSTDLIB +SOAP_FMAC1 void SOAP_FMAC2 soap_print_fault(struct soap*, FILE*); +SOAP_FMAC1 void SOAP_FMAC2 soap_print_fault_location(struct soap*, FILE*); +#endif + +SOAP_FMAC1 int SOAP_FMAC2 soap_s2byte(struct soap*, const char*, char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2short(struct soap*, const char*, short*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2int(struct soap*, const char*, int*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2long(struct soap*, const char*, long*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2LONG64(struct soap*, const char*, LONG64*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2float(struct soap*, const char*, float*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2double(struct soap*, const char*, double*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedByte(struct soap*, const char*, unsigned char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedShort(struct soap*, const char*, unsigned short*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedInt(struct soap*, const char*, unsigned int*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedLong(struct soap*, const char*, unsigned long*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2ULONG64(struct soap*, const char*, ULONG64*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2string(struct soap*, const char*, char**); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2QName(struct soap*, const char*, char**); + +#ifndef WITH_LEAN +SOAP_FMAC1 int SOAP_FMAC2 soap_s2wchar(struct soap*, const char*, wchar_t**); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2dateTime(struct soap*, const char*, time_t*); +SOAP_FMAC1 char* SOAP_FMAC2 soap_s2base64(struct soap*, const unsigned char*, char*, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_s2hex(struct soap*, const unsigned char*, char*, int); +#endif + +SOAP_FMAC1 const char* SOAP_FMAC2 soap_byte2s(struct soap*, char); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_short2s(struct soap*, short); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_int2s(struct soap*, int); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_long2s(struct soap*, long); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_LONG642s(struct soap*, LONG64); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_float2s(struct soap*, float); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_double2s(struct soap*, double); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedByte2s(struct soap*, unsigned char); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedShort2s(struct soap*, unsigned short); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedInt2s(struct soap*, unsigned int); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedLong2s(struct soap*, unsigned long); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_ULONG642s(struct soap*, ULONG64); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_QName2s(struct soap*, const char*); + +#ifndef WITH_LEAN +SOAP_FMAC1 const char* SOAP_FMAC2 soap_wchar2s(struct soap*, const wchar_t*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_dateTime2s(struct soap*, time_t); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_base642s(struct soap*, const char*, char*, size_t, int*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_hex2s(struct soap*, const char*, char*, size_t, int*); +#endif + + +SOAP_FMAC1 int* SOAP_FMAC2 soap_inint(struct soap*, const char *tag, int *p, const char *, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_inbyte(struct soap*, const char *tag, char *p, const char *, int); +SOAP_FMAC1 long* SOAP_FMAC2 soap_inlong(struct soap*, const char *tag, long *p, const char *, int); +SOAP_FMAC1 LONG64* SOAP_FMAC2 soap_inLONG64(struct soap*, const char *tag, LONG64 *p, const char *, int); +SOAP_FMAC1 short* SOAP_FMAC2 soap_inshort(struct soap*, const char *tag, short *p, const char *, int); +SOAP_FMAC1 float* SOAP_FMAC2 soap_infloat(struct soap*, const char *tag, float *p, const char *, int); +SOAP_FMAC1 double* SOAP_FMAC2 soap_indouble(struct soap*, const char *tag, double *p, const char *, int); +SOAP_FMAC1 unsigned char* SOAP_FMAC2 soap_inunsignedByte(struct soap*, const char *tag, unsigned char *p, const char *, int); +SOAP_FMAC1 unsigned short* SOAP_FMAC2 soap_inunsignedShort(struct soap*, const char *tag, unsigned short *p, const char *, int); +SOAP_FMAC1 unsigned int* SOAP_FMAC2 soap_inunsignedInt(struct soap*, const char *tag, unsigned int *p, const char *, int); +SOAP_FMAC1 unsigned long* SOAP_FMAC2 soap_inunsignedLong(struct soap*, const char *tag, unsigned long *p, const char *, int); +SOAP_FMAC1 ULONG64* SOAP_FMAC2 soap_inULONG64(struct soap*, const char *tag, ULONG64 *p, const char *, int); +SOAP_FMAC1 char** SOAP_FMAC2 soap_instring(struct soap*, const char *tag, char **p, const char *, int, int, long, long); +SOAP_FMAC1 char** SOAP_FMAC2 soap_inliteral(struct soap*, const char *tag, char **p); + +#ifndef WITH_LEAN +SOAP_FMAC1 time_t* SOAP_FMAC2 soap_indateTime(struct soap*, const char *tag, time_t *p, const char *, int); +#endif + +#ifndef WITH_LEANER +SOAP_FMAC1 wchar_t** SOAP_FMAC2 soap_inwstring(struct soap*, const char *tag, wchar_t **p, const char *, int, long, long); +SOAP_FMAC1 wchar_t** SOAP_FMAC2 soap_inwliteral(struct soap*, const char *tag, wchar_t **p); +#endif + +SOAP_FMAC1 int SOAP_FMAC2 soap_outbyte(struct soap*, const char *tag, int id, const char *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outshort(struct soap*, const char *tag, int id, const short *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outint(struct soap*, const char *tag, int id, const int *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outlong(struct soap*, const char *tag, int id, const long *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outLONG64(struct soap*, const char *tag, int id, const LONG64 *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outfloat(struct soap*, const char *tag, int id, const float *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outdouble(struct soap*, const char *tag, int id, const double *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedByte(struct soap*, const char *tag, int id, const unsigned char *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedShort(struct soap*, const char *tag, int id, const unsigned short *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedInt(struct soap*, const char *tag, int id, const unsigned int *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedLong(struct soap*, const char *tag, int id, const unsigned long *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outULONG64(struct soap*, const char *tag, int id, const ULONG64 *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outstring(struct soap*, const char *tag, int id, char *const*p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outliteral(struct soap*, const char *tag, char *const*p, const char *type); + +#ifndef WITH_LEAN +SOAP_FMAC1 int SOAP_FMAC2 soap_outdateTime(struct soap*, const char *tag, int id, const time_t *p, const char *, int); +#endif + +#ifndef WITH_LEANER +SOAP_FMAC1 int SOAP_FMAC2 soap_outwstring(struct soap*, const char *tag, int id, wchar_t *const*p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outwliteral(struct soap*, const char *tag, wchar_t *const*p, const char *type); +#endif + +#ifndef WITH_LEANER +SOAP_FMAC1 int SOAP_FMAC2 soap_attachment(struct soap *, const char*, int, const void*, const struct soap_array*, const char*, const char*, const char*, int, const char*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_move(struct soap*, long); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_tell(struct soap*); +SOAP_FMAC1 char* SOAP_FMAC2 soap_dime_option(struct soap*, unsigned short, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getdimehdr(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getdime(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putdimehdr(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putdime(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getmimehdr(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getmime(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putmimehdr(struct soap*, struct soap_multipart*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putmime(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_dime(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_mime(struct soap*, const char *boundary, const char *start); +SOAP_FMAC1 void SOAP_FMAC2 soap_clr_dime(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_clr_mime(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_dime_attachment(struct soap*, char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_mime_attachment(struct soap*, char *ptr, size_t size, enum soap_mime_encoding encoding, const char *type, const char *id, const char *location, const char *description); +SOAP_FMAC1 void SOAP_FMAC2 soap_post_check_mime_attachments(struct soap *soap); +SOAP_FMAC1 int SOAP_FMAC2 soap_check_mime_attachments(struct soap *soap); +SOAP_FMAC1 struct soap_multipart* SOAP_FMAC2 soap_get_mime_attachment(struct soap *soap, void *handle); +SOAP_FMAC1 struct soap_multipart* SOAP_FMAC2 soap_next_multipart(struct soap_multipart*); +SOAP_FMAC1 int SOAP_FMAC2 soap_match_cid(struct soap*, const char*, const char*); +#endif + +SOAP_FMAC1 int SOAP_FMAC2 soap_register_plugin_arg(struct soap*, int (*fcreate)(struct soap*, struct soap_plugin*, void*), void*); +SOAP_FMAC1 void* SOAP_FMAC2 soap_lookup_plugin(struct soap*, const char*); + +SOAP_FMAC1 const char* SOAP_FMAC2 soap_attr_value(struct soap *soap, const char *name, int flag); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_attr(struct soap *soap, const char *name, const char *value); +SOAP_FMAC1 void SOAP_FMAC2 soap_clr_attr(struct soap *soap); + +#ifdef WITH_COOKIES +SOAP_FMAC1 void SOAP_FMAC2 soap_getcookies(struct soap *soap, const char *val); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_encode_cookie(const char*, char*, size_t); +SOAP_FMAC1 extern struct soap_cookie* SOAP_FMAC2 soap_set_cookie(struct soap*, const char*, const char*, const char*, const char*); +SOAP_FMAC1 extern struct soap_cookie* SOAP_FMAC2 soap_cookie(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern char* SOAP_FMAC2 soap_cookie_value(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern char* SOAP_FMAC2 soap_env_cookie_value(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern time_t SOAP_FMAC2 soap_cookie_expire(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern int SOAP_FMAC2 soap_set_cookie_expire(struct soap*, const char*, long, const char*, const char*); +SOAP_FMAC1 extern int SOAP_FMAC2 soap_set_cookie_session(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern int SOAP_FMAC2 soap_clr_cookie_session(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern void SOAP_FMAC2 soap_clr_cookie(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern int SOAP_FMAC2 soap_getenv_cookies(struct soap*); +SOAP_FMAC1 extern struct soap_cookie* SOAP_FMAC2 soap_copy_cookies(struct soap*, struct soap*); +SOAP_FMAC1 extern void SOAP_FMAC2 soap_free_cookies(struct soap*); +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.9l.c b/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.9l.c new file mode 100644 index 0000000..ca9dc91 --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.9l.c @@ -0,0 +1,14748 @@ +/* + +stdsoap2.c[pp] 2.7.9l + +gSOAP runtime + +gSOAP XML Web services tools +Copyright (C) 2000-2007, Robert van Engelen, Genivia Inc., All Rights Reserved. +This part of the software is released under one of the following licenses: +GPL, the gSOAP public license, or Genivia's license for commercial use. +-------------------------------------------------------------------------------- +Contributors: + +Wind River Systems Inc., for the following additions under gSOAP public license: + - vxWorks compatible (#define VXWORKS) +-------------------------------------------------------------------------------- +gSOAP public license. + +The contents of this file are subject to the gSOAP Public License Version 1.3 +(the "License"); you may not use this file except in compliance with the +License. You may obtain a copy of the License at +http://www.cs.fsu.edu/~engelen/soaplicense.html +Software distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +for the specific language governing rights and limitations under the License. + +The Initial Developer of the Original Code is Robert A. van Engelen. +Copyright (C) 2000-2007, Robert van Engelen, Genivia Inc., All Rights Reserved. +-------------------------------------------------------------------------------- +GPL license. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA + +Author contact information: +engelen@genivia.com / engelen@acm.org +-------------------------------------------------------------------------------- +A commercial use license is available from Genivia, Inc., contact@genivia.com +-------------------------------------------------------------------------------- + +Installation note: + +Win32 build needs winsock.dll (Visual C++ "wsock32.lib") +To do this in Visual C++ 6.0, go to "Project", "settings", select the "Link" +tab (the project file needs to be selected in the file view) and add +"wsock32.lib" to the "Object/library modules" entry + +On Mac OS X with gcc (GCC) 3.1 20020420 (prerelease) you MUST compile with +-fstack_check when using -O2 because gcc 3.1 has a bug that smashes the stack +when locally allocated data exceeds 64K. + +*/ + +#ifdef AS400 +# pragma convert(819) /* EBCDIC to ASCII */ +#endif + +#include "stdsoap2.h" + +#ifdef __BORLANDC__ +# pragma warn -8060 +#else +# ifdef WIN32 +# ifdef UNDER_CE +# pragma comment(lib, "winsock.lib") +# else +# pragma comment(lib, "wsock32.lib") +# endif +# pragma warning(disable : 4996) // disable deprecation warnings +# endif +#endif + +#ifdef __cplusplus +SOAP_SOURCE_STAMP("@(#) stdsoap2.cpp ver 2.7.9l 2007-09-26 00:00:00 GMT") +extern "C" { +#else +SOAP_SOURCE_STAMP("@(#) stdsoap2.c ver 2.7.9l 2007-09-26 00:00:00 GMT") +#endif + +/* 8bit character representing unknown/nonrepresentable character data (e.g. not supported by current locale with multibyte support enabled) */ +#ifndef SOAP_UNKNOWN_CHAR +#define SOAP_UNKNOWN_CHAR (127) +#endif + +/* EOF=-1 */ +#define SOAP_LT (soap_wchar)(-2) /* XML character '<' */ +#define SOAP_TT (soap_wchar)(-3) /* XML character '' */ +#define SOAP_QT (soap_wchar)(-5) /* XML character '"' */ +#define SOAP_AP (soap_wchar)(-6) /* XML character ''' */ + +#define soap_blank(c) ((c) >= 0 && (c) <= 32) +#define soap_notblank(c) ((c) > 32) + +#if defined(WIN32) && !defined(UNDER_CE) +#define soap_hash_ptr(p) ((PtrToUlong(p) >> 3) & (SOAP_PTRHASH - 1)) +#else +#define soap_hash_ptr(p) ((size_t)(((unsigned long)(p) >> 3) & (SOAP_PTRHASH-1))) +#endif + +#ifdef SOAP_DEBUG +static void soap_init_logs(struct soap*); +static void soap_close_logfile(struct soap*, int); +static void soap_set_logfile(struct soap*, int, const char*); +#endif + +#ifdef SOAP_MEM_DEBUG +static void soap_init_mht(struct soap*); +static void soap_free_mht(struct soap*); +static void soap_track_unlink(struct soap*, const void*); +#endif + +#ifndef PALM_2 +static int soap_set_error(struct soap*, const char*, const char*, const char*, const char*, int); +static int soap_copy_fault(struct soap*, const char*, const char*, const char*, const char*); +static int soap_getattrval(struct soap*, char*, size_t, soap_wchar); +#endif + +#ifndef PALM_1 +static soap_wchar soap_char(struct soap*); +static soap_wchar soap_get_pi(struct soap*); +static int soap_isxdigit(int); +static void *fplugin(struct soap*, const char*); +#ifndef WITH_NOIDREF +static void soap_update_ptrs(struct soap*, char*, char*, char*, char*); +static int soap_has_copies(struct soap*, const char*, const char*); +static void soap_init_iht(struct soap*); +static void soap_free_iht(struct soap*); +static void soap_init_pht(struct soap*); +static void soap_free_pht(struct soap*); +#endif +#endif + +#ifndef WITH_LEAN +static const char *soap_set_validation_fault(struct soap*, const char*, const char*); +static int soap_isnumeric(struct soap*, const char*); +static struct soap_nlist *soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized); +static void soap_pop_ns(struct soap *soap); +static void soap_utilize_ns(struct soap *soap, const char *tag, size_t n); +#endif + +#ifndef WITH_LEANER +#ifndef PALM_1 +static struct soap_multipart *soap_new_multipart(struct soap*, struct soap_multipart**, struct soap_multipart**, char*, size_t); +static int soap_putdimefield(struct soap*, const char*, size_t); +static char *soap_getdimefield(struct soap*, size_t); +static void soap_select_mime_boundary(struct soap*); +static int soap_valid_mime_boundary(struct soap*); +static void soap_resolve_attachment(struct soap*, struct soap_multipart*); +#endif +#endif + +#ifdef WITH_GZIP +static int soap_getgziphdr(struct soap*); +#endif + +#ifdef WITH_OPENSSL +static int ssl_init_done = 0; +static int ssl_auth_init(struct soap*); +static int ssl_verify_callback(int, X509_STORE_CTX*); +static int ssl_password(char*, int, int, void *); +/* This callback is included for future references. It should not be deleted +static DH *ssl_tmp_dh(SSL*, int, int); +*/ +#endif + +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +#ifndef PALM_1 +static const char *soap_decode(char*, size_t, const char*, const char*); +#endif +#endif + +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static soap_wchar soap_getchunkchar(struct soap*); +static const char *http_error(struct soap*, int); +static int http_post(struct soap*, const char*, const char*, int, const char*, const char*, size_t); +static int http_get(struct soap*); +static int http_send_header(struct soap*, const char*); +static int http_post_header(struct soap*, const char*, const char*); +static int http_response(struct soap*, int, size_t); +static int http_parse(struct soap*); +static int http_parse_header(struct soap*, const char*, const char*); +#endif +#endif + +#ifndef WITH_NOIO +#ifndef PALM_1 +static int fsend(struct soap*, const char*, size_t); +static size_t frecv(struct soap*, char*, size_t); +static int tcp_init(struct soap*); +static const char *tcp_error(struct soap*); +#ifndef WITH_LEAN +static size_t frecv_stop(struct soap*, char*, size_t); +#endif +#ifndef WITH_IPV6 +static int tcp_gethost(struct soap*, const char *addr, struct in_addr *inaddr); +#endif +static SOAP_SOCKET tcp_connect(struct soap*, const char *endpoint, const char *host, int port); +static SOAP_SOCKET tcp_accept(struct soap*, SOAP_SOCKET, struct sockaddr*, int*); +static int tcp_disconnect(struct soap*); +static int tcp_closesocket(struct soap*, SOAP_SOCKET); +static int tcp_shutdownsocket(struct soap*, SOAP_SOCKET, int); +static const char *soap_strerror(struct soap*); +#endif +#endif + +#if defined(PALM) && !defined(PALM_2) +unsigned short errno; +#endif + +#ifndef PALM_1 +static const char soap_env1[42] = "http://schemas.xmlsoap.org/soap/envelope/"; +static const char soap_enc1[42] = "http://schemas.xmlsoap.org/soap/encoding/"; +static const char soap_env2[40] = "http://www.w3.org/2003/05/soap-envelope"; +static const char soap_enc2[40] = "http://www.w3.org/2003/05/soap-encoding"; +static const char soap_rpc[35] = "http://www.w3.org/2003/05/soap-rpc"; +#endif + +#ifndef PALM_1 +const struct soap_double_nan soap_double_nan = {0xFFFFFFFF, 0xFFFFFFFF}; +static const char soap_base64o[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char soap_base64i[81] = "\76XXX\77\64\65\66\67\70\71\72\73\74\75XXXXXXX\00\01\02\03\04\05\06\07\10\11\12\13\14\15\16\17\20\21\22\23\24\25\26\27\30\31XXXXXX\32\33\34\35\36\37\40\41\42\43\44\45\46\47\50\51\52\53\54\55\56\57\60\61\62\63"; +#endif + +#ifndef WITH_LEAN +static const char soap_indent[11] = "\n\t\t\t\t\t\t\t\t\t"; +/* Alternative indentation form for SOAP_XML_INDENT: +static const char soap_indent[21] = "\n "; +*/ +#endif + +#ifndef SOAP_CANARY +# define SOAP_CANARY (0xC0DE) +#endif + +static const char soap_padding[4] = "\0\0\0"; +#define SOAP_STR_PADDING (soap_padding) +#define SOAP_STR_EOS (soap_padding) +#define SOAP_NON_NULL (soap_padding) + +#ifndef WITH_LEAN +static const struct soap_code_map html_entity_codes[] = /* entities for XHTML parsing */ +{ { 160, "nbsp" }, + { 161, "iexcl" }, + { 162, "cent" }, + { 163, "pound" }, + { 164, "curren" }, + { 165, "yen" }, + { 166, "brvbar" }, + { 167, "sect" }, + { 168, "uml" }, + { 169, "copy" }, + { 170, "ordf" }, + { 171, "laquo" }, + { 172, "not" }, + { 173, "shy" }, + { 174, "reg" }, + { 175, "macr" }, + { 176, "deg" }, + { 177, "plusmn" }, + { 178, "sup2" }, + { 179, "sup3" }, + { 180, "acute" }, + { 181, "micro" }, + { 182, "para" }, + { 183, "middot" }, + { 184, "cedil" }, + { 185, "sup1" }, + { 186, "ordm" }, + { 187, "raquo" }, + { 188, "frac14" }, + { 189, "frac12" }, + { 190, "frac34" }, + { 191, "iquest" }, + { 192, "Agrave" }, + { 193, "Aacute" }, + { 194, "Acirc" }, + { 195, "Atilde" }, + { 196, "Auml" }, + { 197, "Aring" }, + { 198, "AElig" }, + { 199, "Ccedil" }, + { 200, "Egrave" }, + { 201, "Eacute" }, + { 202, "Ecirc" }, + { 203, "Euml" }, + { 204, "Igrave" }, + { 205, "Iacute" }, + { 206, "Icirc" }, + { 207, "Iuml" }, + { 208, "ETH" }, + { 209, "Ntilde" }, + { 210, "Ograve" }, + { 211, "Oacute" }, + { 212, "Ocirc" }, + { 213, "Otilde" }, + { 214, "Ouml" }, + { 215, "times" }, + { 216, "Oslash" }, + { 217, "Ugrave" }, + { 218, "Uacute" }, + { 219, "Ucirc" }, + { 220, "Uuml" }, + { 221, "Yacute" }, + { 222, "THORN" }, + { 223, "szlig" }, + { 224, "agrave" }, + { 225, "aacute" }, + { 226, "acirc" }, + { 227, "atilde" }, + { 228, "auml" }, + { 229, "aring" }, + { 230, "aelig" }, + { 231, "ccedil" }, + { 232, "egrave" }, + { 233, "eacute" }, + { 234, "ecirc" }, + { 235, "euml" }, + { 236, "igrave" }, + { 237, "iacute" }, + { 238, "icirc" }, + { 239, "iuml" }, + { 240, "eth" }, + { 241, "ntilde" }, + { 242, "ograve" }, + { 243, "oacute" }, + { 244, "ocirc" }, + { 245, "otilde" }, + { 246, "ouml" }, + { 247, "divide" }, + { 248, "oslash" }, + { 249, "ugrave" }, + { 250, "uacute" }, + { 251, "ucirc" }, + { 252, "uuml" }, + { 253, "yacute" }, + { 254, "thorn" }, + { 255, "yuml" }, + { 0, NULL } +}; +#endif + +#ifndef WITH_NOIO +#ifndef WITH_LEAN +static const struct soap_code_map h_error_codes[] = +{ +#ifdef HOST_NOT_FOUND + { HOST_NOT_FOUND, "Host not found" }, +#endif +#ifdef TRY_AGAIN + { TRY_AGAIN, "Try Again" }, +#endif +#ifdef NO_RECOVERY + { NO_RECOVERY, "No Recovery" }, +#endif +#ifdef NO_DATA + { NO_DATA, "No Data" }, +#endif +#ifdef NO_ADDRESS + { NO_ADDRESS, "No Address" }, +#endif + { 0, NULL } +}; +#endif +#endif + +#ifndef WITH_NOHTTP +#ifndef WITH_LEAN +static const struct soap_code_map h_http_error_codes[] = +{ { 200, "OK" }, + { 201, "Created" }, + { 202, "Accepted" }, + { 203, "Non-Authoritative Information" }, + { 204, "No Content" }, + { 205, "Reset Content" }, + { 206, "Partial Content" }, + { 300, "Multiple Choices" }, + { 301, "Moved Permanently" }, + { 302, "Found" }, + { 303, "See Other" }, + { 304, "Not Modified" }, + { 305, "Use Proxy" }, + { 307, "Temporary Redirect" }, + { 400, "Bad Request" }, + { 401, "Unauthorized" }, + { 402, "Payment Required" }, + { 403, "Forbidden" }, + { 404, "Not Found" }, + { 405, "Method Not Allowed" }, + { 406, "Not Acceptable" }, + { 407, "Proxy Authentication Required" }, + { 408, "Request Time-out" }, + { 409, "Conflict" }, + { 410, "Gone" }, + { 411, "Length Required" }, + { 412, "Precondition Failed" }, + { 413, "Request Entity Too Large" }, + { 414, "Request-URI Too Large" }, + { 415, "Unsupported Media Type" }, + { 416, "Requested range not satisfiable" }, + { 417, "Expectation Failed" }, + { 500, "Internal Server Error" }, + { 501, "Not Implemented" }, + { 502, "Bad Gateway" }, + { 503, "Service Unavailable" }, + { 504, "Gateway Time-out" }, + { 505, "HTTP Version not supported" }, + { 0, NULL } +}; +#endif +#endif + +#ifdef WITH_OPENSSL +static const struct soap_code_map h_ssl_error_codes[] = +{ +#define _SSL_ERROR(e) { e, #e } + _SSL_ERROR(SSL_ERROR_SSL), + _SSL_ERROR(SSL_ERROR_ZERO_RETURN), + _SSL_ERROR(SSL_ERROR_WANT_READ), + _SSL_ERROR(SSL_ERROR_WANT_WRITE), + _SSL_ERROR(SSL_ERROR_WANT_CONNECT), + _SSL_ERROR(SSL_ERROR_WANT_X509_LOOKUP), + _SSL_ERROR(SSL_ERROR_SYSCALL), + { 0, NULL } +}; +#endif + +#ifndef WITH_LEANER +static const struct soap_code_map mime_codes[] = +{ { SOAP_MIME_7BIT, "7bit" }, + { SOAP_MIME_8BIT, "8bit" }, + { SOAP_MIME_BINARY, "binary" }, + { SOAP_MIME_QUOTED_PRINTABLE, "quoted-printable" }, + { SOAP_MIME_BASE64, "base64" }, + { SOAP_MIME_IETF_TOKEN, "ietf-token" }, + { SOAP_MIME_X_TOKEN, "x-token" }, + { 0, NULL } +}; +#endif + +#ifdef WIN32 +static int tcp_done = 0; +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +fsend(struct soap *soap, const char *s, size_t n) +{ register int nwritten, err; +#if defined(__cplusplus) && !defined(WITH_LEAN) + if (soap->os) + { soap->os->write(s, (std::streamsize)n); + if (soap->os->good()) + return SOAP_OK; + soap->errnum = 0; + return SOAP_EOF; + } +#endif + while (n) + { if (soap_valid_socket(soap->socket)) + { +#ifndef WITH_LEAN + if (soap->send_timeout) + { +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + return SOAP_FD_EXCEEDED; /* Hint: MUST increase FD_SETSIZE */ +#endif + for (;;) + { struct timeval timeout; + fd_set fd; + register int r; + if (soap->send_timeout > 0) + { timeout.tv_sec = soap->send_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->send_timeout/1000000; + timeout.tv_usec = -soap->send_timeout%1000000; + } + FD_ZERO(&fd); + FD_SET(soap->socket, &fd); +#ifdef WITH_OPENSSL + if (soap->ssl) + r = select((int)soap->socket + 1, &fd, &fd, &fd, &timeout); + else +#endif + r = select((int)soap->socket + 1, NULL, &fd, &fd, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + return SOAP_EOF; + } + err = soap_socket_errno(soap->socket); + if (err != SOAP_EINTR && err != SOAP_EAGAIN) + { soap->errnum = err; + return SOAP_EOF; + } + } + } +#endif +#ifdef WITH_OPENSSL + if (soap->ssl) + nwritten = SSL_write(soap->ssl, s, (int)n); + else if (soap->bio) + nwritten = BIO_write(soap->bio, s, (int)n); + else +#endif +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + { if (soap->peerlen) + nwritten = sendto(soap->socket, s, n, soap->socket_flags, (struct sockaddr*)&soap->peer, soap->peerlen); + else + nwritten = send(soap->socket, s, n, soap->socket_flags); + /* retry and back-off algorithm */ + /* TODO: this is not very clear from specs so verify and limit conditions under which we should loop (e.g. ENOBUFS) */ + if (nwritten < 0) + { struct timeval timeout; + fd_set fd; + int udp_repeat; + int udp_delay; +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + return SOAP_FD_EXCEEDED; /* Hint: MUST increase FD_SETSIZE */ +#endif + if ((soap->connect_flags & SO_BROADCAST)) + udp_repeat = 3; /* SOAP-over-UDP MULTICAST_UDP_REPEAT - 1 */ + else + udp_repeat = 1; /* SOAP-over-UDP UNICAST_UDP_REPEAT - 1 */ + udp_delay = (soap_random % 201) + 50; /* UDP_MIN_DELAY .. UDP_MAX_DELAY */ + do + { timeout.tv_sec = 0; + timeout.tv_usec = 1000 * udp_delay; /* ms */ + FD_ZERO(&fd); + FD_SET(soap->socket, &fd); + select((int)soap->socket + 1, NULL, NULL, &fd, &timeout); + if (soap->peerlen) + nwritten = sendto(soap->socket, s, n, soap->socket_flags, (struct sockaddr*)&soap->peer, soap->peerlen); + else + nwritten = send(soap->socket, s, n, soap->socket_flags); + udp_delay <<= 1; + if (udp_delay > 500) /* UDP_UPPER_DELAY */ + udp_delay = 500; + } + while (nwritten < 0 && --udp_repeat > 0); + } + } + else +#endif +#if !defined(PALM) && !defined(AS400) + nwritten = send(soap->socket, s, (int)n, soap->socket_flags); +#else + nwritten = send(soap->socket, (void*)s, n, soap->socket_flags); +#endif + if (nwritten <= 0) + { register int r = 0; + err = soap_socket_errno(soap->socket); +#ifdef WITH_OPENSSL + if (soap->ssl && (r = SSL_get_error(soap->ssl, nwritten)) != SSL_ERROR_NONE && r != SSL_ERROR_WANT_READ && r != SSL_ERROR_WANT_WRITE) + { soap->errnum = err; + return SOAP_EOF; + } +#endif + if (err == SOAP_EWOULDBLOCK || err == SOAP_EAGAIN) + { +#ifndef WITH_LEAN + struct timeval timeout; + fd_set fd; +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + return SOAP_FD_EXCEEDED; /* Hint: MUST increase FD_SETSIZE */ +#endif + if (soap->send_timeout > 0) + { timeout.tv_sec = soap->send_timeout; + timeout.tv_usec = 0; + } + else if (soap->send_timeout < 0) + { timeout.tv_sec = -soap->send_timeout/1000000; + timeout.tv_usec = -soap->send_timeout%1000000; + } + else + { timeout.tv_sec = 0; + timeout.tv_usec = 10000; + } + FD_ZERO(&fd); + FD_SET(soap->socket, &fd); +#ifdef WITH_OPENSSL + if (soap->ssl && r == SSL_ERROR_WANT_READ) + r = select((int)soap->socket + 1, &fd, NULL, &fd, &timeout); + else + r = select((int)soap->socket + 1, NULL, &fd, &fd, &timeout); +#else + r = select((int)soap->socket + 1, NULL, &fd, &fd, &timeout); +#endif + if (r < 0 && (r = soap_socket_errno(soap->socket)) != SOAP_EINTR) + { soap->errnum = r; + return SOAP_EOF; + } +#endif + } + else if (err && err != SOAP_EINTR) + { soap->errnum = err; + return SOAP_EOF; + } + nwritten = 0; /* and call write() again */ + } + } + else + { +#ifdef WITH_FASTCGI + nwritten = fwrite((void*)s, 1, n, stdout); + fflush(stdout); +#else +#ifdef UNDER_CE + nwritten = fwrite(s, 1, n, soap->sendfd); +#else +#ifdef VXWORKS +#ifdef WMW_RPM_IO + if (soap->rpmreqid) + nwritten = (httpBlockPut(soap->rpmreqid, s, n) == 0) ? n : -1; + else +#endif + nwritten = fwrite(s, sizeof(char), n, fdopen(soap->sendfd, "w")); +#else + nwritten = write(soap->sendfd, s, (unsigned int)n); +#endif +#endif +#endif + if (nwritten <= 0) + { err = soap_errno; + if (err && err != SOAP_EINTR && err != SOAP_EWOULDBLOCK && err != SOAP_EAGAIN) + { soap->errnum = err; + return SOAP_EOF; + } + nwritten = 0; /* and call write() again */ + } + } + n -= nwritten; + s += nwritten; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send_raw(struct soap *soap, const char *s, size_t n) +{ if (!n) + return SOAP_OK; + if (soap->mode & SOAP_IO_LENGTH) + { soap->count += n; +#ifndef WITH_LEANER + if (soap->fpreparesend && (soap->mode & SOAP_IO) != SOAP_IO_STORE) + return soap->error = soap->fpreparesend(soap, s, n); +#endif + return SOAP_OK; + } + if (soap->mode & SOAP_IO) + { register size_t i = SOAP_BUFLEN - soap->bufidx; + while (n >= i) + { memcpy(soap->buf + soap->bufidx, s, i); + soap->bufidx = SOAP_BUFLEN; + if (soap_flush(soap)) + return soap->error; + s += i; + n -= i; + i = SOAP_BUFLEN; + } + memcpy(soap->buf + soap->bufidx, s, n); + soap->bufidx += n; + return SOAP_OK; + } + return soap_flush_raw(soap, s, n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_flush(struct soap *soap) +{ register size_t n = soap->bufidx; + if (n) + { soap->bufidx = 0; +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { soap->d_stream.next_in = (Byte*)soap->buf; + soap->d_stream.avail_in = (unsigned int)n; +#ifdef WITH_GZIP + soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)n); +#endif + do + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating %u bytes\n", soap->d_stream.avail_in)); + if (deflate(&soap->d_stream, Z_NO_FLUSH) != Z_OK) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to deflate: %s\n", soap->d_stream.msg?soap->d_stream.msg:"")); + return soap->error = SOAP_ZLIB_ERROR; + } + if (!soap->d_stream.avail_out) + { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN)) + return soap->error; + soap->d_stream.next_out = (Byte*)soap->z_buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + } + } while (soap->d_stream.avail_in); + } + else +#endif + return soap_flush_raw(soap, soap->buf, n); + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_flush_raw(struct soap *soap, const char *s, size_t n) +{ if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) + { register char *t; + if (!(t = (char*)soap_push_block(soap, n))) + return soap->error = SOAP_EOM; + memcpy(t, s, n); +#ifndef WITH_LEANER + if (soap->fpreparesend) + return soap->error = soap->fpreparesend(soap, s, n); +#endif + return SOAP_OK; + } +#ifndef WITH_LEANER + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) + { char t[16]; + sprintf(t, "\r\n%lX\r\n" + (soap->chunksize ? 0 : 2), (unsigned long)n); + DBGMSG(SENT, t, strlen(t)); + if ((soap->error = soap->fsend(soap, t, strlen(t)))) + return soap->error; + soap->chunksize += n; + } + DBGMSG(SENT, s, n); +#endif + return soap->error = soap->fsend(soap, s, n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send(struct soap *soap, const char *s) +{ if (s) + return soap_send_raw(soap, s, strlen(s)); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send2(struct soap *soap, const char *s1, const char *s2) +{ if (soap_send(soap, s1)) + return soap->error; + return soap_send(soap, s2); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send3(struct soap *soap, const char *s1, const char *s2, const char *s3) +{ if (soap_send(soap, s1) + || soap_send(soap, s2)) + return soap->error; + return soap_send(soap, s3); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static size_t +frecv(struct soap *soap, char *s, size_t n) +{ register int r; +#ifdef PALM + register int timeouts = 6000; /* Palm: 1 min timeout for SSL */ +#endif + soap->errnum = 0; +#if defined(__cplusplus) && !defined(WITH_LEAN) + if (soap->is) + { if (soap->is->good()) + return soap->is->read(s, (std::streamsize)n).gcount(); + return 0; + } +#endif + if (soap_valid_socket(soap->socket)) + { for (;;) + { +#ifdef WITH_OPENSSL + register int err = 0; +#endif +#ifndef WITH_LEAN +#ifdef WITH_OPENSSL + if (soap->recv_timeout && !soap->ssl) /* SSL: sockets are nonblocking */ +#else + if (soap->recv_timeout) +#endif + { +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + { soap->error = SOAP_FD_EXCEEDED; + return 0; /* Hint: MUST increase FD_SETSIZE */ + } +#endif + for (;;) + { struct timeval timeout; + fd_set fd; + if (soap->recv_timeout > 0) + { timeout.tv_sec = soap->recv_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->recv_timeout/1000000; + timeout.tv_usec = -soap->recv_timeout%1000000; + } + FD_ZERO(&fd); + FD_SET(soap->socket, &fd); + r = select((int)soap->socket + 1, &fd, NULL, &fd, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + return 0; + } + r = soap_socket_errno(soap->socket); + if (r != SOAP_EINTR && r != SOAP_EAGAIN) + { soap->errnum = r; + return 0; + } + } + } +#endif +#ifdef WITH_OPENSSL + if (soap->ssl) + { r = SSL_read(soap->ssl, s, (int)n); + if (r > 0) + return (size_t)r; + err = SSL_get_error(soap->ssl, r); + if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) + return 0; + } + else if (soap->bio) + { r = BIO_read(soap->bio, s, (int)n); + if (r > 0) + return (size_t)r; + return 0; + } + else +#endif + { +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + { SOAP_SOCKLEN_T k = (SOAP_SOCKLEN_T)sizeof(soap->peer); + memset((void*)&soap->peer, 0, sizeof(soap->peer)); + r = recvfrom(soap->socket, s, n, soap->socket_flags, (struct sockaddr*)&soap->peer, &k); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */ + soap->peerlen = (size_t)k; +#ifndef WITH_IPV6 + soap->ip = ntohl(soap->peer.sin_addr.s_addr); +#endif + } + else +#endif + r = recv(soap->socket, s, (int)n, soap->socket_flags); +#ifdef PALM + /* CycleSyncDisplay(curStatusMsg); */ +#endif + if (r >= 0) + return (size_t)r; + r = soap_socket_errno(soap->socket); + if (r != SOAP_EINTR && r != SOAP_EAGAIN && r != SOAP_EWOULDBLOCK) + { soap->errnum = r; + return 0; + } + } +#ifndef WITH_LEAN + { struct timeval timeout; + fd_set fd; + if (soap->recv_timeout > 0) + { timeout.tv_sec = soap->recv_timeout; + timeout.tv_usec = 0; + } + else if (soap->recv_timeout < 0) + { timeout.tv_sec = -soap->recv_timeout/1000000; + timeout.tv_usec = -soap->recv_timeout%1000000; + } + else + { timeout.tv_sec = 0; + timeout.tv_usec = 10000; + } +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + { soap->error = SOAP_FD_EXCEEDED; + return 0; /* Hint: MUST increase FD_SETSIZE */ + } +#endif + FD_ZERO(&fd); + FD_SET(soap->socket, &fd); +#ifdef WITH_OPENSSL + if (soap->ssl && err == SSL_ERROR_WANT_WRITE) + r = select((int)soap->socket + 1, NULL, &fd, &fd, &timeout); + else + r = select((int)soap->socket + 1, &fd, NULL, &fd, &timeout); +#else + r = select((int)soap->socket + 1, &fd, NULL, &fd, &timeout); +#endif + if (r < 0 && (r = soap_socket_errno(soap->socket)) != SOAP_EINTR) + { soap->errnum = r; + return 0; + } + if (!r && soap->recv_timeout) + { soap->errnum = 0; + return 0; + } + } +#endif +#ifdef PALM + r = soap_socket_errno(soap->socket); + if (r != SOAP_EINTR && timeouts-- <= 0) + { soap->errnum = r; + return 0; + } +#endif + } + } +#ifdef WITH_FASTCGI + return fread(s, 1, n, stdin); +#else +#ifdef UNDER_CE + return fread(s, 1, n, soap->recvfd); +#else +#ifdef WMW_RPM_IO + if (soap->rpmreqid) + r = httpBlockRead(soap->rpmreqid, s, n); + else +#endif + r = read(soap->recvfd, s, (unsigned int)n); + if (r >= 0) + return (size_t)r; + soap->errnum = soap_errno; + return 0; +#endif +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +#ifndef WITH_NOIO +#ifndef PALM_1 +static size_t +frecv_stop(struct soap *soap, char *s, size_t n) +{ return 0; +} +#endif +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static soap_wchar +soap_getchunkchar(struct soap *soap) +{ if (soap->bufidx < soap->buflen) + return soap->buf[soap->bufidx++]; + soap->bufidx = 0; + soap->buflen = soap->chunkbuflen = soap->frecv(soap, soap->buf, SOAP_BUFLEN); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket %d\n", (unsigned int)soap->buflen, soap->socket)); + DBGMSG(RECV, soap->buf, soap->buflen); + if (soap->buflen) + return soap->buf[soap->bufidx++]; + return EOF; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +soap_isxdigit(int c) +{ return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv_raw(struct soap *soap) +{ register size_t ret; +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { if (soap->d_stream.next_out == Z_NULL) + return EOF; + if (soap->d_stream.avail_in || !soap->d_stream.avail_out) + { register int r; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflating\n")); + soap->d_stream.next_out = (Byte*)soap->buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + r = inflate(&soap->d_stream, Z_NO_FLUSH); + if (r == Z_OK || r == Z_STREAM_END) + { soap->bufidx = 0; + ret = soap->buflen = SOAP_BUFLEN - soap->d_stream.avail_out; + if (soap->zlib_in == SOAP_ZLIB_GZIP) + soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)ret); + if (r == Z_STREAM_END) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out)); + soap->z_ratio_in = (float)soap->d_stream.total_in / (float)soap->d_stream.total_out; + soap->d_stream.next_out = Z_NULL; + } + if (ret) + { soap->count += ret; + DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- decompressed ----\n")); + DBGMSG(RECV, soap->buf, ret); + DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n----\n")); + return SOAP_OK; + } + } + else if (r != Z_BUF_ERROR) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate error: %s\n", soap->d_stream.msg?soap->d_stream.msg:"")); + soap->d_stream.next_out = Z_NULL; + soap->error = SOAP_ZLIB_ERROR; + return EOF; + } + } +zlib_again: + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK && !soap->chunksize) + { memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN); + soap->buflen = soap->z_buflen; + } + DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- compressed ----\n")); + } +#endif +#ifndef WITH_NOHTTP + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) /* read HTTP chunked transfer */ + { +chunk_again: + if (soap->chunksize) + { soap->buflen = ret = soap->frecv(soap, soap->buf, soap->chunksize > SOAP_BUFLEN ? SOAP_BUFLEN : soap->chunksize); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk: read %u bytes\n", (unsigned int)ret)); + DBGMSG(RECV, soap->buf, ret); + soap->bufidx = 0; + soap->chunksize -= ret; + } + else + { register soap_wchar c; + char *t, tmp[8]; + t = tmp; + if (!soap->chunkbuflen) + { soap->chunkbuflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes (chunked) from socket %d\n", (unsigned int)ret, soap->socket)); + DBGMSG(RECV, soap->buf, ret); + soap->bufidx = 0; + if (!ret) + return soap->ahead = EOF; + } + else + soap->bufidx = soap->buflen; + soap->buflen = soap->chunkbuflen; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Getting chunk size (idx=%u len=%u)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen)); + while (!soap_isxdigit((int)(c = soap_getchunkchar(soap)))) + { if ((int)c == EOF) + return soap->ahead = EOF; + } + do + *t++ = (char)c; + while (soap_isxdigit((int)(c = soap_getchunkchar(soap))) && t - tmp < 7); + while ((int)c != EOF && c != '\n') + c = soap_getchunkchar(soap); + if ((int)c == EOF) + return soap->ahead = EOF; + *t = '\0'; + soap->chunksize = soap_strtoul(tmp, &t, 16); + if (!soap->chunksize) + { soap->chunkbuflen = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of chunked message\n")); + while ((int)c != EOF && c != '\n') + c = soap_getchunkchar(soap); + return soap->ahead = EOF; + } + soap->buflen = soap->bufidx + soap->chunksize; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving buf len to idx=%u len=%u (%s)\n", (unsigned int)soap->bufidx, (unsigned int)soap->buflen, tmp)); + if (soap->buflen > soap->chunkbuflen) + { soap->buflen = soap->chunkbuflen; + soap->chunksize -= soap->buflen - soap->bufidx; + soap->chunkbuflen = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Passed end of buffer for chunked HTTP (%u bytes left)\n", (unsigned int)(soap->buflen - soap->bufidx))); + } + else if (soap->chunkbuflen) + soap->chunksize = 0; + ret = soap->buflen - soap->bufidx; + if (!ret) + goto chunk_again; + } + } + else +#endif + { soap->bufidx = 0; + soap->buflen = ret = soap->frecv(soap, soap->buf, SOAP_BUFLEN); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Read %u bytes from socket %d\n", (unsigned int)ret, soap->socket)); + DBGMSG(RECV, soap->buf, ret); + } +#ifndef WITH_LEANER + if (soap->fpreparerecv && (soap->error = soap->fpreparerecv(soap, soap->buf, ret))) + return soap->error; +#endif +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { register int r; + memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); + soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx); + soap->d_stream.avail_in = (unsigned int)ret; + soap->d_stream.next_out = (Byte*)soap->buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + r = inflate(&soap->d_stream, Z_NO_FLUSH); + if (r == Z_OK || r == Z_STREAM_END) + { soap->bufidx = 0; + soap->z_buflen = soap->buflen; + soap->buflen = ret = SOAP_BUFLEN - soap->d_stream.avail_out; + if (soap->zlib_in == SOAP_ZLIB_GZIP) + soap->z_crc = crc32(soap->z_crc, (Byte*)soap->buf, (unsigned int)soap->buflen); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %u bytes\n", (unsigned int)ret)); + if (!ret) + goto zlib_again; + if (r == Z_STREAM_END) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out)); + soap->z_ratio_in = (float)soap->d_stream.total_in / (float)soap->d_stream.total_out; + soap->d_stream.next_out = Z_NULL; + } + DBGLOG(RECV, SOAP_MESSAGE(fdebug, "\n---- decompressed ----\n")); + DBGMSG(RECV, soap->buf, ret); + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to inflate: (%d) %s\n", r, soap->d_stream.msg?soap->d_stream.msg:"")); + soap->d_stream.next_out = Z_NULL; + soap->error = SOAP_ZLIB_ERROR; + return EOF; + } + } +#endif + soap->count += ret; + return !ret; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv(struct soap *soap) +{ +#ifndef WITH_LEANER + if (soap->mode & SOAP_ENC_DIME) + { if (soap->dime.buflen) + { char *s; + int i; + unsigned char tmp[12]; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME hdr for chunked DIME is in buffer\n")); + soap->count += soap->dime.buflen - soap->buflen; + soap->buflen = soap->dime.buflen; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Skip padding (%ld bytes)\n", -(long)soap->dime.size&3)); + for (i = -(long)soap->dime.size&3; i > 0; i--) + { soap->bufidx++; + if (soap->bufidx >= soap->buflen) + if (soap_recv_raw(soap)) + return EOF; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME hdr for next chunk\n")); + s = (char*)tmp; + for (i = 12; i > 0; i--) + { *s++ = soap->buf[soap->bufidx++]; + if (soap->bufidx >= soap->buflen) + if (soap_recv_raw(soap)) + return EOF; + } + soap->dime.flags = tmp[0] & 0x7; + soap->dime.size = ((size_t)tmp[8] << 24) | ((size_t)tmp[9] << 16) | ((size_t)tmp[10] << 8) | ((size_t)tmp[11]); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME chunk (%u bytes)\n", (unsigned int)soap->dime.size)); + if (soap->dime.flags & SOAP_DIME_CF) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "More chunking\n")); + soap->dime.chunksize = soap->dime.size; + if (soap->buflen - soap->bufidx >= soap->dime.size) + { soap->dime.buflen = soap->buflen; + soap->buflen = soap->bufidx + soap->dime.chunksize; + } + else + soap->dime.chunksize -= soap->buflen - soap->bufidx; + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Last chunk\n")); + soap->dime.buflen = 0; + soap->dime.chunksize = 0; + } + soap->count = soap->buflen - soap->bufidx; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%u bytes remaining\n", (unsigned int)soap->count)); + return SOAP_OK; + } + if (soap->dime.chunksize) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get next DIME hdr for chunked DIME (%u bytes chunk)\n", (unsigned int)soap->dime.chunksize)); + if (soap_recv_raw(soap)) + return EOF; + if (soap->buflen - soap->bufidx >= soap->dime.chunksize) + { soap->dime.buflen = soap->buflen; + soap->count -= soap->buflen - soap->bufidx - soap->dime.chunksize; + soap->buflen = soap->bufidx + soap->dime.chunksize; + } + else + soap->dime.chunksize -= soap->buflen - soap->bufidx; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%lu bytes remaining, count=%u\n", (unsigned long)(soap->buflen-soap->bufidx), (unsigned int)soap->count)); + return SOAP_OK; + } + } +#endif + return soap_recv_raw(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +soap_wchar +SOAP_FMAC2 +soap_getchar(struct soap *soap) +{ register soap_wchar c; + c = soap->ahead; + if (c) + { if (c != EOF) + soap->ahead = 0; + return c; + } + return soap_get1(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +const struct soap_code_map* +SOAP_FMAC2 +soap_code(const struct soap_code_map *code_map, const char *str) +{ if (code_map && str) + { while (code_map->string) + { if (!strcmp(str, code_map->string)) /* case sensitive */ + return code_map; + code_map++; + } + } + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +long +SOAP_FMAC2 +soap_code_int(const struct soap_code_map *code_map, const char *str, long other) +{ if (code_map) + { while (code_map->string) + { if (!soap_tag_cmp(str, code_map->string)) /* case insensitive */ + return code_map->code; + code_map++; + } + } + return other; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_code_str(const struct soap_code_map *code_map, long code) +{ if (!code_map) + return NULL; + while (code_map->code != code && code_map->string) + code_map++; + return code_map->string; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +long +SOAP_FMAC2 +soap_code_bits(const struct soap_code_map *code_map, const char *str) +{ register long bits = 0; + if (code_map) + { while (str && *str) + { const struct soap_code_map *p; + for (p = code_map; p->string; p++) + { register size_t n = strlen(p->string); + if (!strncmp(p->string, str, n) && soap_blank(str[n])) + { bits |= p->code; + str += n; + while (*str > 0 && *str <= 32) + str++; + break; + } + } + if (!p->string) + return 0; + } + } + return bits; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_code_list(struct soap *soap, const struct soap_code_map *code_map, long code) +{ register char *t = soap->tmpbuf; + if (code_map) + { while (code_map->string) + { if (code_map->code & code) + { register const char *s = code_map->string; + if (t != soap->tmpbuf) + *t++ = ' '; + while (*s && t < soap->tmpbuf + sizeof(soap->tmpbuf) - 1) + *t++ = *s++; + if (t == soap->tmpbuf + sizeof(soap->tmpbuf) - 1) + break; + } + code_map++; + } + } + *t = '\0'; + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static soap_wchar +soap_char(struct soap *soap) +{ char tmp[8]; + register int i; + register soap_wchar c; + register char *s = tmp; + for (i = 0; i < 7; i++) + { c = soap_get1(soap); + if (c == ';' || (int)c == EOF) + break; + *s++ = (char)c; + } + *s = '\0'; + if (*tmp == '#') + { if (tmp[1] == 'x' || tmp[1] == 'X') + return soap_strtol(tmp + 2, NULL, 16); + return atol(tmp + 1); + } + if (!strcmp(tmp, "lt")) + return '<'; + if (!strcmp(tmp, "gt")) + return '>'; + if (!strcmp(tmp, "amp")) + return '&'; + if (!strcmp(tmp, "quot")) + return '"'; + if (!strcmp(tmp, "apos")) + return '\''; +#ifndef WITH_LEAN + return (soap_wchar)soap_code_int(html_entity_codes, tmp, SOAP_UNKNOWN_CHAR); +#else + return SOAP_UNKNOWN_CHAR; /* use this to represent unknown code */ +#endif +} +#endif + +/******************************************************************************/ +#ifdef WITH_LEAN +#ifndef PALM_1 +soap_wchar +soap_get0(struct soap *soap) +{ if (soap->bufidx >= soap->buflen && soap_recv(soap)) + return EOF; + return (unsigned char)soap->buf[soap->bufidx]; +} +#endif +#endif + +/******************************************************************************/ +#ifdef WITH_LEAN +#ifndef PALM_1 +soap_wchar +soap_get1(struct soap *soap) +{ if (soap->bufidx >= soap->buflen && soap_recv(soap)) + return EOF; + return (unsigned char)soap->buf[soap->bufidx++]; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +soap_wchar +SOAP_FMAC2 +soap_get(struct soap *soap) +{ register soap_wchar c; + c = soap->ahead; + if (c) + { if ((int)c != EOF) + soap->ahead = 0; + } + else + c = soap_get1(soap); + while ((int)c != EOF) + { if (soap->cdata) + { if (c == ']') + { c = soap_get1(soap); + if (c == ']') + { c = soap_get0(soap); + if (c == '>') + { soap->cdata = 0; + soap_get1(soap); + c = soap_get1(soap); + } + else + { soap_unget(soap, ']'); + return ']'; + } + } + else + { soap_revget1(soap); + return ']'; + } + } + else + return c; + } + switch (c) + { case '<': + do c = soap_get1(soap); + while (soap_blank(c)); + if (c == '!' || c == '?' || c == '%') + { register int k = 1; + if (c == '!') + { c = soap_get1(soap); + if (c == '[') + { do c = soap_get1(soap); + while ((int)c != EOF && c != '['); + if ((int)c == EOF) + break; + soap->cdata = 1; + c = soap_get1(soap); + continue; + } + if (c == '-' && (c = soap_get1(soap)) == '-') + { do + { c = soap_get1(soap); + if (c == '-' && (c = soap_get1(soap)) == '-') + break; + } while ((int)c != EOF); + } + } + else if (c == '?') + c = soap_get_pi(soap); + while ((int)c != EOF) + { if (c == '<') + k++; + else if (c == '>') + { if (--k <= 0) + break; + } + c = soap_get1(soap); + } + if ((int)c == EOF) + break; + c = soap_get1(soap); + continue; + } + if (c == '/') + return SOAP_TT; + soap_revget1(soap); + return SOAP_LT; + case '>': + return SOAP_GT; + case '"': + return SOAP_QT; + case '\'': + return SOAP_AP; + case '&': + return soap_char(soap) | 0x80000000; + } + break; + } + return c; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static soap_wchar +soap_get_pi(struct soap *soap) +{ char buf[64]; + register char *s = buf; + register int i = sizeof(buf); + register soap_wchar c = soap_getchar(soap); + /* This is a quick way to parse XML PI and we could use a callback instead to + * enable applications to intercept processing instructions */ + while ((int)c != EOF && c != '?') + { if (--i > 0) + { if (soap_blank(c)) + c = ' '; + *s++ = (char)c; + } + c = soap_getchar(soap); + } + *s = '\0'; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "XML PI \n", buf)); + if (!strncmp(buf, "xml ", 4)) + { s = strstr(buf, " encoding="); + if (s && s[10]) + { if (!soap_tag_cmp(s + 11, "iso-8859-1*") + || !soap_tag_cmp(s + 11, "latin1*")) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to latin1 encoding\n")); + soap->mode |= SOAP_ENC_LATIN; + } + else if (!soap_tag_cmp(s + 11, "utf-8*")) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Switching to utf-8 encoding\n")); + soap->mode &= ~SOAP_ENC_LATIN; + } + } + } + if ((int)c != EOF) + c = soap_getchar(soap); + return c; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_move(struct soap *soap, long n) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Moving %ld bytes forward\n", (long)n)); + for (; n > 0; n--) + if ((int)soap_getchar(soap) == EOF) + return SOAP_EOF; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_tell(struct soap *soap) +{ return soap->count - soap->buflen + soap->bufidx - (soap->ahead != 0); +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_pututf8(struct soap *soap, register unsigned long c) +{ char tmp[16]; + if (c < 0x80 && c >= 0x20) + { *tmp = (char)c; + return soap_send_raw(soap, tmp, 1); + } +#ifndef WITH_LEAN + if (c >= 0x80 && (soap->mode & SOAP_XML_CANONICAL)) + { register char *t = tmp; + if (c < 0x0800) + *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); + else + { if (c < 0x010000) + *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + else + { if (c < 0x200000) + *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + else + { if (c < 0x04000000) + *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + else + { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + } + *t++ = (char)(0x80 | (c & 0x3F)); + *t = '\0'; + } + else +#endif + sprintf(tmp, "&#%lu;", c); + return soap_send(soap, tmp); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +soap_wchar +SOAP_FMAC2 +soap_getutf8(struct soap *soap) +{ register soap_wchar c, c1, c2, c3, c4; + c = soap->ahead; + if (c > 0xFF) + { soap->ahead = 0; + return c; + } +again: + c = soap_get(soap); + if (c < 0x80 || (soap->mode & SOAP_ENC_LATIN)) + return c; + c1 = soap_get1(soap); + if (c1 < 0x80) + { soap_revget1(soap); /* doesn't look like this is UTF8 */ + return c; + } + c1 &= 0x3F; + if (c < 0xE0) + return ((soap_wchar)(c & 0x1F) << 6) | c1; + c2 = (soap_wchar)soap_get1(soap) & 0x3F; + if (c == 0xEF && c1 == 0x3B && c2 == 0x3F) /* ignore UTF-8 BOM */ + goto again; + if (c < 0xF0) + return ((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2; + c3 = (soap_wchar)soap_get1(soap) & 0x3F; + if (c < 0xF8) + return ((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3; + c4 = (soap_wchar)soap_get1(soap) & 0x3F; + if (c < 0xFC) + return ((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4; + return ((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(soap_get1(soap) & 0x3F); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_puthex(struct soap *soap, const unsigned char *s, int n) +{ char d[2]; + register int i; +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { if (!(soap->dom->data = soap_s2hex(soap, s, NULL, n))) + return soap->error; + return SOAP_OK; + } +#endif + for (i = 0; i < n; i++) + { register int m = *s++; + d[0] = (char)((m >> 4) + (m > 159 ? '7' : '0')); + m &= 0x0F; + d[1] = (char)(m + (m > 9 ? '7' : '0')); + if (soap_send_raw(soap, d, 2)) + return soap->error; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +unsigned char* +SOAP_FMAC2 +soap_gethex(struct soap *soap, int *n) +{ +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { soap->dom->data = soap_string_in(soap, 0, -1, -1); + return (unsigned char*)soap_hex2s(soap, soap->dom->data, NULL, 0, n); + } +#endif +#ifdef WITH_FAST + soap->labidx = 0; + for (;;) + { register char *s; + register size_t i, k; + if (soap_append_lab(soap, NULL, 0)) + return NULL; + s = soap->labbuf + soap->labidx; + k = soap->lablen - soap->labidx; + soap->labidx = soap->lablen; + for (i = 0; i < k; i++) + { register char d1, d2; + register soap_wchar c; + c = soap_get(soap); + if (soap_isxdigit(c)) + { d1 = (char)c; + c = soap_get(soap); + if (soap_isxdigit(c)) + d2 = (char)c; + else + { soap->error = SOAP_TYPE; + return NULL; + } + } + else + { unsigned char *p; + soap_unget(soap, c); + if (n) + *n = (int)(soap->lablen + i - k); + p = (unsigned char*)soap_malloc(soap, soap->lablen + i - k); + if (p) + memcpy(p, soap->labbuf, soap->lablen + i - k); + return p; + } + *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'); + } + } +#else + if (soap_new_block(soap)) + return NULL; + for (;;) + { register int i; + register char *s = (char*)soap_push_block(soap, SOAP_BLKLEN); + if (!s) + { soap_end_block(soap); + return NULL; + } + for (i = 0; i < SOAP_BLKLEN; i++) + { register char d1, d2; + register soap_wchar c = soap_get(soap); + if (soap_isxdigit(c)) + { d1 = (char)c; + c = soap_get(soap); + if (soap_isxdigit(c)) + d2 = (char)c; + else + { soap_end_block(soap); + soap->error = SOAP_TYPE; + return NULL; + } + } + else + { unsigned char *p; + soap_unget(soap, c); + if (n) + *n = (int)soap_size_block(soap, i); + p = (unsigned char*)soap_save_block(soap, NULL, 0); + return p; + } + *s++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'); + } + } +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putbase64(struct soap *soap, const unsigned char *s, int n) +{ register int i; + register unsigned long m; + char d[4]; + if (!s) + return SOAP_OK; +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { if (!(soap->dom->data = soap_s2base64(soap, s, NULL, n))) + return soap->error; + return SOAP_OK; + } +#endif + for (; n > 2; n -= 3, s += 3) + { m = s[0]; + m = (m << 8) | s[1]; + m = (m << 8) | s[2]; + for (i = 4; i > 0; m >>= 6) + d[--i] = soap_base64o[m & 0x3F]; + if (soap_send_raw(soap, d, 4)) + return soap->error; + } + if (n > 0) + { m = 0; + for (i = 0; i < n; i++) + m = (m << 8) | *s++; + for (; i < 3; i++) + m <<= 8; + for (i++; i > 0; m >>= 6) + d[--i] = soap_base64o[m & 0x3F]; + for (i = 3; i > n; i--) + d[i] = '='; + if (soap_send_raw(soap, d, 4)) + return soap->error; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +unsigned char* +SOAP_FMAC2 +soap_getbase64(struct soap *soap, int *n, int malloc_flag) +{ +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { soap->dom->data = soap_string_in(soap, 0, -1, -1); + return (unsigned char*)soap_base642s(soap, soap->dom->data, NULL, 0, n); + } +#endif +#ifdef WITH_FAST + soap->labidx = 0; + for (;;) + { register size_t i, k; + register char *s; + if (soap_append_lab(soap, NULL, 2)) + return NULL; + s = soap->labbuf + soap->labidx; + k = soap->lablen - soap->labidx; + soap->labidx = 3 * (soap->lablen / 3); + if (!s) + return NULL; + if (k > 2) + { for (i = 0; i < k - 2; i += 3) + { register unsigned long m = 0; + register int j = 0; + do + { register soap_wchar c = soap_get(soap); + if (c == '=' || c < 0) + { unsigned char *p; + switch (j) + { case 2: + *s++ = (char)((m >> 4) & 0xFF); + i++; + break; + case 3: + *s++ = (char)((m >> 10) & 0xFF); + *s++ = (char)((m >> 2) & 0xFF); + i += 2; + } + if (n) + *n = (int)(soap->lablen + i - k); + p = (unsigned char*)soap_malloc(soap, soap->lablen + i - k); + if (p) + memcpy(p, soap->labbuf, soap->lablen + i - k); + if (c >= 0) + { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT) + ; + } + soap_unget(soap, c); + return p; + } + c -= '+'; + if (c >= 0 && c <= 79) + { register int b = soap_base64i[c]; + if (b >= 64) + { soap->error = SOAP_TYPE; + return NULL; + } + m = (m << 6) + b; + j++; + } + else if (!soap_blank(c + '+')) + { soap->error = SOAP_TYPE; + return NULL; + } + } while (j < 4); + *s++ = (char)((m >> 16) & 0xFF); + *s++ = (char)((m >> 8) & 0xFF); + *s++ = (char)(m & 0xFF); + } + } + } +#else + if (soap_new_block(soap)) + return NULL; + for (;;) + { register int i; + register char *s = (char*)soap_push_block(soap, 3 * SOAP_BLKLEN); /* must be multiple of 3 */ + if (!s) + { soap_end_block(soap); + return NULL; + } + for (i = 0; i < SOAP_BLKLEN; i++) + { register unsigned long m = 0; + register int j = 0; + do + { register soap_wchar c = soap_get(soap); + if (c == '=' || c < 0) + { unsigned char *p; + i *= 3; + switch (j) + { case 2: + *s++ = (char)((m >> 4) & 0xFF); + i++; + break; + case 3: + *s++ = (char)((m >> 10) & 0xFF); + *s++ = (char)((m >> 2) & 0xFF); + i += 2; + } + if (n) + *n = (int)soap_size_block(soap, i); + p = (unsigned char*)soap_save_block(soap, NULL, 0); + if (c >= 0) + { while ((int)((c = soap_get(soap)) != EOF) && c != SOAP_LT && c != SOAP_TT) + ; + } + soap_unget(soap, c); + return p; + } + c -= '+'; + if (c >= 0 && c <= 79) + { int b = soap_base64i[c]; + if (b >= 64) + { soap->error = SOAP_TYPE; + return NULL; + } + m = (m << 6) + b; + j++; + } + else if (!soap_blank(c)) + { soap->error = SOAP_TYPE; + return NULL; + } + } while (j < 4); + *s++ = (char)((m >> 16) & 0xFF); + *s++ = (char)((m >> 8) & 0xFF); + *s++ = (char)(m & 0xFF); + } + } +#endif +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_xop_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options) +{ /* Check MTOM xop:Include element (within hex/base64Binary) */ + /* TODO: this code to be obsoleted with new import/xop.h conventions */ + int body = soap->body; /* should save type too? */ + if (!soap_peek_element(soap)) + { if (!soap_element_begin_in(soap, "xop:Include", 0, NULL) && *soap->href) + { if (soap_dime_forward(soap, ptr, size, id, type, options)) + return soap->error; + } + if (soap->body && soap_element_end_in(soap, NULL)) + return soap->error; + } + soap->body = body; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_dime_forward(struct soap *soap, unsigned char **ptr, int *size, char **id, char **type, char **options) +{ struct soap_xlist *xp; + *ptr = NULL; + *size = 0; + *type = NULL; + *options = NULL; + *id = soap_strdup(soap, soap->href); + if (!*id) + return SOAP_OK; + xp = (struct soap_xlist*)SOAP_MALLOC(soap, sizeof(struct soap_xlist)); + if (!xp) + return soap->error = SOAP_EOM; + xp->next = soap->xlist; + xp->ptr = ptr; + xp->size = size; + xp->id = *id; + xp->type = type; + xp->options = options; + soap->xlist = xp; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_strdup(struct soap *soap, const char *s) +{ char *t = NULL; + if (s && (t = (char*)soap_malloc(soap, strlen(s) + 1))) + strcpy(t, s); + return t; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_new_block(struct soap *soap) +{ struct soap_blist *p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New block sequence (prev=%p)\n", soap->blist)); + if (!(p = (struct soap_blist*)SOAP_MALLOC(soap, sizeof(struct soap_blist)))) + return SOAP_EOM; + p->next = soap->blist; + p->ptr = NULL; + p->size = 0; + soap->blist = p; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_push_block(struct soap *soap, size_t n) +{ char *p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push block of %u bytes (%u bytes total)\n", (unsigned int)n, (unsigned int)soap->blist->size + (unsigned int)n)); + if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(char*) + sizeof(size_t)))) + { soap->error = SOAP_EOM; + return NULL; + } + *(char**)p = soap->blist->ptr; + *(size_t*)(p + sizeof(char*)) = n; + soap->blist->ptr = p; + soap->blist->size += n; + return p + sizeof(char*) + sizeof(size_t); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_pop_block(struct soap *soap) +{ char *p; + if (!soap->blist->ptr) + return; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop block\n")); + p = soap->blist->ptr; + soap->blist->size -= *(size_t*)(p + sizeof(char*)); + soap->blist->ptr = *(char**)p; + SOAP_FREE(soap, p); +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static void +soap_update_ptrs(struct soap *soap, char *start, char *end, char *p1, char *p2) +{ int i; + register struct soap_ilist *ip = NULL; + register struct soap_flist *fp = NULL; +#ifndef WITH_LEANER + register struct soap_xlist *xp = NULL; +#endif + register void *p, **q; + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { if (ip->ptr && (char*)ip->ptr >= start && (char*)ip->ptr < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", ip->id, ip->ptr, (char*)ip->ptr + (p1-p2))); + ip->ptr = (char*)ip->ptr + (p1-p2); + } + for (q = &ip->link; q; q = (void**)p) + { p = *q; + if (p && (char*)p >= start && (char*)p < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Link update id='%s' %p\n", ip->id, p)); + *q = (char*)p + (p1-p2); + } + } + for (q = &ip->copy; q; q = (void**)p) + { p = *q; + if (p && (char*)p >= start && (char*)p < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy chain update id='%s' %p\n", ip->id, p)); + *q = (char*)p + (p1-p2); + } + } + for (fp = ip->flist; fp; fp = fp->next) + { if ((char*)fp->ptr >= start && (char*)fp->ptr < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy list update id='%s' %p\n", ip->id, fp)); + fp->ptr = (char*)fp->ptr + (p1-p2); + } + } + } + } +#ifndef WITH_LEANER + for (xp = soap->xlist; xp; xp = xp->next) + { if (xp->ptr && (char*)xp->ptr >= start && (char*)xp->ptr < end) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update id='%s' %p -> %p\n", xp->id?xp->id:"", xp->ptr, (char*)xp->ptr + (p1-p2))); + xp->ptr = (unsigned char**)((char*)xp->ptr + (p1-p2)); + xp->size = (int*)((char*)xp->size + (p1-p2)); + xp->type = (char**)((char*)xp->type + (p1-p2)); + xp->options = (char**)((char*)xp->options + (p1-p2)); + } + } +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static int +soap_has_copies(struct soap *soap, register const char *start, register const char *end) +{ register int i; + register struct soap_ilist *ip = NULL; + register struct soap_flist *fp = NULL; + register const char *p; + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { for (p = (const char*)ip->copy; p; p = *(const char**)p) + if (p >= start && p < end) + return SOAP_ERR; + for (fp = ip->flist; fp; fp = fp->next) + if ((const char*)fp->ptr >= start && (const char*)fp->ptr < end) + return SOAP_ERR; + } + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_resolve(struct soap *soap) +{ register int i; + register struct soap_ilist *ip = NULL; + register struct soap_flist *fp = NULL; + short flag; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data\n")); + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { if (ip->ptr) + { register void *p, **q, *r; + q = (void**)ip->link; + ip->link = NULL; + r = ip->ptr; + DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing link chain to resolve id='%s'\n", ip->id)); + while (q) + { p = *q; + *q = r; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "... link %p -> %p\n", q, r)); + q = (void**)p; + } + } + else if (*ip->id == '#') + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Missing data for id='%s'\n", ip->id)); + strcpy(soap->id, ip->id + 1); + return soap->error = SOAP_MISSING_ID; + } + } + } + do + { flag = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution phase\n")); + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { if (ip->ptr && !soap_has_copies(soap, (const char*)ip->ptr, (const char*)ip->ptr + ip->size)) + { if (ip->copy) + { register void *p, **q = (void**)ip->copy; + DBGLOG(TEST, if (q) SOAP_MESSAGE(fdebug, "Traversing copy chain to resolve id='%s'\n", ip->id)); + ip->copy = NULL; + do + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... copy %p -> %p (%u bytes)\n", ip->ptr, q, (unsigned int)ip->size)); + p = *q; + memcpy(q, ip->ptr, ip->size); + q = (void**)p; + } while (q); + flag = 1; + } + for (fp = ip->flist; fp; fp = ip->flist) + { register unsigned int k = fp->level; + register void *p = ip->ptr; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving forwarded data type=%d location=%p level=%u,%u id='%s'\n", ip->type, p, ip->level, fp->level, ip->id)); + while (ip->level < k) + { register void **q = (void**)soap_malloc(soap, sizeof(void*)); + if (!q) + return soap->error; + *q = p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level, new location=%p holds=%p...\n", q, *q)); + p = (void*)q; + k--; + } + if (fp->fcopy) + fp->fcopy(soap, ip->type, fp->type, fp->ptr, fp->len, p, ip->size); + else + soap_fcopy(soap, ip->type, fp->type, fp->ptr, fp->len, p, ip->size); + ip->flist = fp->next; + SOAP_FREE(soap, fp); + flag = 1; + } + } + } + } + } while (flag); +#ifdef SOAP_DEBUG + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = ip->next) + { if (ip->copy || ip->flist) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution error: forwarded data for id='%s' could not be propagated, please report this problem to the developers\n", ip->id)); + } + } + } +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolution done\n")); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_size_block(struct soap *soap, size_t n) +{ if (soap->blist->ptr) + { soap->blist->size -= *(size_t*)(soap->blist->ptr + sizeof(char*)) - n; + *(size_t*)(soap->blist->ptr + sizeof(char*)) = n; + } + return soap->blist->size; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_first_block(struct soap *soap) +{ char *p, *q, *r; + p = soap->blist->ptr; + if (!p) + return NULL; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "First block\n")); + r = NULL; + do + { q = *(char**)p; + *(char**)p = r; + r = p; + p = q; + } while (p); + soap->blist->ptr = r; + return r + sizeof(char*) + sizeof(size_t); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_next_block(struct soap *soap) +{ char *p; + p = soap->blist->ptr; + if (p) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Next block\n")); + soap->blist->ptr = *(char**)p; + SOAP_FREE(soap, p); + if (soap->blist->ptr) + return soap->blist->ptr + sizeof(char*) + sizeof(size_t); + } + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_block_size(struct soap *soap) +{ return *(size_t*)(soap->blist->ptr + sizeof(char*)); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_end_block(struct soap *soap) +{ struct soap_blist *bp; + char *p, *q; + bp = soap->blist; + if (bp) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of block sequence, free all remaining blocks\n")); + for (p = bp->ptr; p; p = q) + { q = *(char**)p; + SOAP_FREE(soap, p); + } + soap->blist = bp->next; + SOAP_FREE(soap, bp); + } + DBGLOG(TEST, if (soap->blist) SOAP_MESSAGE(fdebug, "Restore previous block sequence\n")); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_save_block(struct soap *soap, char *p, int flag) +{ register size_t n; + register char *q, *s; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Save all blocks in contiguous memory space of %u bytes (%p->%p)\n", (unsigned int)soap->blist->size, soap->blist->ptr, p)); + if (soap->blist->size) + { if (!p) + p = (char*)soap_malloc(soap, soap->blist->size); + if (p) + { for (s = p, q = soap_first_block(soap); q; q = soap_next_block(soap)) + { n = soap_block_size(soap); +#ifndef WITH_NOIDREF + if (flag) + soap_update_ptrs(soap, q, q + n, s, q); +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copy %u bytes from %p to %p\n", (unsigned int)n, q, s)); + memcpy(s, q, n); + s += n; + } + } + else + soap->error = SOAP_EOM; + } + soap_end_block(soap); + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putsize(struct soap *soap, const char *type, int size) +{ return soap_putsizes(soap, type, &size, 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putsizes(struct soap *soap, const char *type, const int *size, int dim) +{ return soap_putsizesoffsets(soap, type, size, NULL, dim); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putsizesoffsets(struct soap *soap, const char *type, const int *size, const int *offset, int dim) +{ int i; + if (!type) + return NULL; + if (soap->version == 2) + { sprintf(soap->type, "%s[%d", type, size[0]); + for (i = 1; i < dim; i++) + sprintf(soap->type + strlen(soap->type), " %d", size[i]); + } + else + { if (offset) + { sprintf(soap->type, "%s[%d", type, size[0] + offset[0]); + for (i = 1; i < dim; i++) + sprintf(soap->type + strlen(soap->type), ",%d", size[i] + offset[i]); + } + else + { sprintf(soap->type, "%s[%d", type, size[0]); + for (i = 1; i < dim; i++) + sprintf(soap->type + strlen(soap->type), ",%d", size[i]); + } + strcat(soap->type, "]"); + } + return soap->type; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putoffset(struct soap *soap, int offset) +{ return soap_putoffsets(soap, &offset, 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_putoffsets(struct soap *soap, const int *offset, int dim) +{ register int i; + sprintf(soap->arrayOffset, "[%d", offset[0]); + for (i = 1; i < dim; i++) + sprintf(soap->arrayOffset + strlen(soap->arrayOffset), ",%d", offset[i]); + strcat(soap->arrayOffset, "]"); + return soap->arrayOffset; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_size(const int *size, int dim) +{ register int i, n = size[0]; + for (i = 1; i < dim; i++) + n *= size[i]; + return n; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getoffsets(const char *attr, const int *size, int *offset, int dim) +{ register int i, j = 0; + if (offset) + for (i = 0; i < dim && attr && *attr; i++) + { attr++; + j *= size[i]; + j += offset[i] = (int)atol(attr); + attr = strchr(attr, ','); + } + else + for (i = 0; i < dim && attr && *attr; i++) + { attr++; + j *= size[i]; + j += (int)atol(attr); + attr = strchr(attr, ','); + } + return j; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getsize(const char *attr1, const char *attr2, int *j) +{ register int n, k; + char *s; + *j = 0; + if (!*attr1) + return -1; + if (*attr1 == '[') + attr1++; + n = 1; + for (;;) + { k = (int)soap_strtol(attr1, &s, 10); + n *= k; + if (k < 0 || n > SOAP_MAXARRAYSIZE || s == attr1) + return -1; + attr1 = strchr(s, ','); + if (!attr1) + attr1 = strchr(s, ' '); + if (attr2 && *attr2) + { attr2++; + *j *= k; + k = (int)soap_strtol(attr2, &s, 10); + *j += k; + if (k < 0) + return -1; + attr2 = s; + } + if (!attr1) + break; + attr1++; + } + return n - *j; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getsizes(const char *attr, int *size, int dim) +{ register int i, k, n; + if (!*attr) + return -1; + i = (int)strlen(attr); + n = 1; + do + { for (i = i-1; i >= 0; i--) + if (attr[i] == '[' || attr[i] == ',' || attr[i] == ' ') + break; + k = (int)atol(attr + i + 1); + n *= size[--dim] = k; + if (k < 0 || n > SOAP_MAXARRAYSIZE) + return -1; + } while (i >= 0 && attr[i] != '['); + return n; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getposition(const char *attr, int *pos) +{ register int i, n; + if (!*attr) + return -1; + n = 0; + i = 1; + do + { pos[n++] = (int)atol(attr + i); + while (attr[i] && attr[i] != ',' && attr[i] != ']') + i++; + if (attr[i] == ',') + i++; + } while (n < SOAP_MAXDIMS && attr[i] && attr[i] != ']'); + return n; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_push_namespace(struct soap *soap, const char *id, const char *ns) +{ register struct soap_nlist *np; + register struct Namespace *p; + register short i = -1; + register size_t n, k; + n = strlen(id); + k = strlen(ns) + 1; + p = soap->local_namespaces; + if (p) + { for (i = 0; p->id; p++, i++) + { if (p->ns && !strcmp(ns, p->ns)) + { if (p->out) + { SOAP_FREE(soap, p->out); + p->out = NULL; + } + break; + } + if (p->out) + { if (!strcmp(ns, p->out)) + break; + } + else if (p->in) + { if (!soap_tag_cmp(ns, p->in)) + { if ((p->out = (char*)SOAP_MALLOC(soap, k))) + strcpy(p->out, ns); + break; + } + } + } + if (!p || !p->id) + i = -1; + } + if (i >= 0) + k = 0; + np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k); + if (!np) + return soap->error = SOAP_EOM; + np->next = soap->nlist; + soap->nlist = np; + np->level = soap->level; + np->index = i; + strcpy(np->id, id); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push namespace binding (level=%u) '%s' '%s'\n", soap->level, id, ns)); + if (i < 0) + { np->ns = np->id + n + 1; + strcpy(np->ns, ns); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push NOT OK: no match found for '%s' in namespace mapping table (added to stack anyway)\n", ns)); + } + else + { np->ns = NULL; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Push OK ('%s' matches '%s' in namespace table)\n", id, p->id)); + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_pop_namespace(struct soap *soap) +{ register struct soap_nlist *np, *nq; + for (np = soap->nlist; np && np->level >= soap->level; np = nq) + { nq = np->next; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pop namespace binding (level=%u) '%s'\n", soap->level, np->id)); + SOAP_FREE(soap, np); + } + soap->nlist = np; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_match_namespace(struct soap *soap, const char *id1, const char *id2, size_t n1, size_t n2) +{ register struct soap_nlist *np = soap->nlist; + while (np && (strncmp(np->id, id1, n1) || np->id[n1])) + np = np->next; + if (np) + { if (np->index < 0 + || (soap->local_namespaces[np->index].id + && (strncmp(soap->local_namespaces[np->index].id, id2, n2) + || soap->local_namespaces[np->index].id[n2]))) + return SOAP_NAMESPACE; + return SOAP_OK; + } + if (n1 == 3 && n1 == n2 && !strcmp(id1, "xml") && !strcmp(id1, id2)) + return SOAP_OK; + return soap->error = SOAP_SYNTAX_ERROR; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_current_namespace(struct soap *soap, const char *tag) +{ register struct soap_nlist *np; + register const char *s; + np = soap->nlist; + if (!(s = strchr(tag, ':'))) + { while (np && *np->id) /* find default namespace, if present */ + np = np->next; + } + else + { while (np && (strncmp(np->id, tag, s - tag) || np->id[s - tag])) + np = np->next; + if (!np) + soap->error = SOAP_NAMESPACE; + } + if (np) + { if (np->index >= 0) + return soap->namespaces[np->index].ns; + if (np->ns) + return soap_strdup(soap, np->ns); + } + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_tag_cmp(const char *s, const char *t) +{ for (;;) + { register int c1 = *s; + register int c2 = *t; + if (!c1 || c1 == '"') + break; + if (c2 != '-') + { if (c1 != c2) + { if (c1 >= 'A' && c1 <= 'Z') + c1 += 'a' - 'A'; + if (c2 >= 'A' && c2 <= 'Z') + c2 += 'a' - 'A'; + } + if (c1 != c2) + { if (c2 != '*') + return 1; + c2 = *++t; + if (!c2) + return 0; + if (c2 >= 'A' && c2 <= 'Z') + c2 += 'a' - 'A'; + for (;;) + { c1 = *s; + if (!c1 || c1 == '"') + break; + if (c1 >= 'A' && c1 <= 'Z') + c1 += 'a' - 'A'; + if (c1 == c2 && !soap_tag_cmp(s + 1, t + 1)) + return 0; + s++; + } + break; + } + } + s++; + t++; + } + if (*t == '*' && !t[1]) + return 0; + return *t; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_match_tag(struct soap *soap, const char *tag1, const char *tag2) +{ register const char *s, *t; + register int err; + if (!tag1 || !tag2 || !*tag2) + return SOAP_OK; + s = strchr(tag1, ':'); + t = strchr(tag2, ':'); + if (t) + { if (s) + { if (t[1] && SOAP_STRCMP(s + 1, t + 1)) + return SOAP_TAG_MISMATCH; + if (t != tag2 && (err = soap_match_namespace(soap, tag1, tag2, s - tag1, t - tag2))) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2)); + if (err == SOAP_NAMESPACE) + return SOAP_TAG_MISMATCH; + return err; + } + } + else if (SOAP_STRCMP(tag1, t + 1)) + { return SOAP_TAG_MISMATCH; + } + else if (t != tag2 && (err = soap_match_namespace(soap, tag1, tag2, 0, t - tag2))) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags '%s' and '%s' match but namespaces differ\n", tag1, tag2)); + if (err == SOAP_NAMESPACE) + return SOAP_TAG_MISMATCH; + return err; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags and (default) namespaces match: '%s' '%s'\n", tag1, tag2)); + return SOAP_OK; + } + if (s) + { if (SOAP_STRCMP(s + 1, tag2)) + return SOAP_TAG_MISMATCH; + } + else if (SOAP_STRCMP(tag1, tag2)) + return SOAP_TAG_MISMATCH; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Tags match: '%s' '%s'\n", tag1, tag2)); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_match_array(struct soap *soap, const char *type) +{ if (*soap->arrayType) + if (soap_match_tag(soap, soap->arrayType, type) + && soap_match_tag(soap, soap->arrayType, "xsd:anyType") + && soap_match_tag(soap, soap->arrayType, "xsd:ur-type") + ) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array type mismatch: '%s' '%s'\n", soap->arrayType, type)); + return SOAP_TAG_MISMATCH; + } + return SOAP_OK; +} +#endif + +/******************************************************************************\ + * + * SSL + * +\******************************************************************************/ + +#ifdef WITH_OPENSSL +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_rand() +{ unsigned char buf[4]; + if (!ssl_init_done) + soap_ssl_init(); + RAND_pseudo_bytes(buf, 4); + return *(int*)buf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_ssl_server_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *password, const char *cafile, const char *capath, const char *dhfile, const char *randfile, const char *sid) +{ int err; + soap->keyfile = keyfile; + soap->password = password; + soap->cafile = cafile; + soap->capath = capath; + soap->dhfile = dhfile; + soap->randfile = randfile; + soap->ssl_flags = flags | (dhfile == NULL ? SOAP_SSL_RSA : 0); + if (!(err = soap->fsslauth(soap))) + { if (sid) + SSL_CTX_set_session_id_context(soap->ctx, (unsigned char*)sid, (unsigned int)strlen(sid)); + } + return err; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_ssl_client_context(struct soap *soap, unsigned short flags, const char *keyfile, const char *password, const char *cafile, const char *capath, const char *randfile) +{ soap->keyfile = keyfile; + soap->password = password; + soap->cafile = cafile; + soap->capath = capath; + soap->dhfile = NULL; + soap->ssl_flags = flags; + soap->randfile = randfile; + return soap->fsslauth(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_ssl_init() +{ /* Note: for MT systems, the main program MUST call soap_ssl_init() before any threads are started */ + if (!ssl_init_done) + { ssl_init_done = 1; + SSL_library_init(); +#ifndef WITH_LEAN + SSL_load_error_strings(); +#endif + if (!RAND_load_file("/dev/urandom", 1024)) + { char buf[1024]; + RAND_seed(buf, sizeof(buf)); + while (!RAND_status()) + { int r = rand(); + RAND_seed(&r, sizeof(int)); + } + } + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +const char * +SOAP_FMAC2 +soap_ssl_error(struct soap *soap, int ret) +{ int err = SSL_get_error(soap->ssl, ret); + const char *msg = soap_code_str(h_ssl_error_codes, err); + if (msg) + strcpy(soap->msgbuf, msg); + else + return ERR_error_string(err, soap->msgbuf); + if (ERR_peek_error()) + { unsigned long r; + strcat(soap->msgbuf, "\n"); + while ((r = ERR_get_error())) + ERR_error_string_n(r, soap->msgbuf + strlen(soap->msgbuf), sizeof(soap->msgbuf) - strlen(soap->msgbuf)); + } + else + { switch (ret) + { case 0: + strcpy(soap->msgbuf, "EOF was observed that violates the protocol. The client probably provided invalid authentication information."); + break; + case -1: + sprintf(soap->msgbuf, "Error observed by underlying BIO: %s", strerror(errno)); + break; + } + } + return soap->msgbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +ssl_password(char *buf, int num, int rwflag, void *userdata) +{ if (num < (int)strlen((char*)userdata) + 1) + return 0; + return (int)strlen(strcpy(buf, (char*)userdata)); +} +#endif + +/******************************************************************************/ +/* This callback is included for future references. It should not be deleted +#ifndef PALM_2 +static DH * +ssl_tmp_dh(SSL *ssl, int is_export, int keylength) +{ static DH *dh512 = NULL; + static DH *dh1024 = NULL; + DH *dh; + switch (keylength) + { case 512: + if (!dh512) + { BIO *bio = BIO_new_file("dh512.pem", "r"); + if (bio) + { dh512 = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + return dh512; + } + } + else + return dh512; + default: + if (!dh1024) + { BIO *bio = BIO_new_file("dh1024.pem", "r"); + if (bio) + { dh1024 = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + } + } + dh = dh1024; + } + return dh; +} +#endif +*/ + +/******************************************************************************/ +#ifndef PALM_1 +static int +ssl_auth_init(struct soap *soap) +{ long flags; + int mode; + if (!ssl_init_done) + soap_ssl_init(); + if (!soap->ctx) + { if (!(soap->ctx = SSL_CTX_new(SSLv23_method()))) + return soap_set_receiver_error(soap, "SSL error", "Can't setup context", SOAP_SSL_ERROR); + /* Alters the behavior of SSL read/write: + SSL_CTX_set_mode(soap->ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY); + */ + } + if (soap->randfile) + { if (!RAND_load_file(soap->randfile, -1)) + return soap_set_receiver_error(soap, "SSL error", "Can't load randomness", SOAP_SSL_ERROR); + } + if (soap->cafile || soap->capath) + { if (!SSL_CTX_load_verify_locations(soap->ctx, soap->cafile, soap->capath)) + return soap_set_receiver_error(soap, "SSL error", "Can't read CA file and directory", SOAP_SSL_ERROR); + if (soap->cafile && (soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION)) + SSL_CTX_set_client_CA_list(soap->ctx, SSL_load_client_CA_file(soap->cafile)); + } + if (!SSL_CTX_set_default_verify_paths(soap->ctx)) + return soap_set_receiver_error(soap, "SSL error", "Can't read default CA file and/or directory", SOAP_SSL_ERROR); +/* This code assumes a typical scenario, see alternative code below */ + if (soap->keyfile) + { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile)) + return soap_set_receiver_error(soap, "SSL error", "Can't read certificate key file", SOAP_SSL_ERROR); + if (soap->password) + { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password); + SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password); + } + if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM)) + return soap_set_receiver_error(soap, "SSL error", "Can't read key file", SOAP_SSL_ERROR); + } +/* Suggested alternative approach to check the key file for certs (cafile=NULL): + if (soap->password) + { SSL_CTX_set_default_passwd_cb_userdata(soap->ctx, (void*)soap->password); + SSL_CTX_set_default_passwd_cb(soap->ctx, ssl_password); + } + if (!soap->cafile || !SSL_CTX_use_certificate_chain_file(soap->ctx, soap->cafile)) + { if (soap->keyfile) + { if (!SSL_CTX_use_certificate_chain_file(soap->ctx, soap->keyfile)) + return soap_set_receiver_error(soap, "SSL error", "Can't read certificate or key file", SOAP_SSL_ERROR); + if (!SSL_CTX_use_PrivateKey_file(soap->ctx, soap->keyfile, SSL_FILETYPE_PEM)) + return soap_set_receiver_error(soap, "SSL error", "Can't read key file", SOAP_SSL_ERROR); + } + } +*/ + if ((soap->ssl_flags & SOAP_SSL_RSA)) + { RSA *rsa = RSA_generate_key(1024, RSA_F4, NULL, NULL); + if (!SSL_CTX_set_tmp_rsa(soap->ctx, rsa)) + { if (rsa) + RSA_free(rsa); + return soap_set_receiver_error(soap, "SSL error", "Can't set RSA key", SOAP_SSL_ERROR); + } + RSA_free(rsa); + } + else if (soap->dhfile) + { DH *dh = 0; + BIO *bio; + bio = BIO_new_file(soap->dhfile, "r"); + if (!bio) + return soap_set_receiver_error(soap, "SSL error", "Can't read DH file", SOAP_SSL_ERROR); + dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + if (SSL_CTX_set_tmp_dh(soap->ctx, dh) < 0) + { if (dh) + DH_free(dh); + return soap_set_receiver_error(soap, "SSL error", "Can't set DH parameters", SOAP_SSL_ERROR); + } + DH_free(dh); + } + flags = (SSL_OP_ALL | SSL_OP_NO_SSLv2); + if ((soap->ssl_flags & SOAP_SSLv3)) + flags |= SSL_OP_NO_TLSv1; + if ((soap->ssl_flags & SOAP_TLSv1)) + flags |= SSL_OP_NO_SSLv3; + SSL_CTX_set_options(soap->ctx, flags); + if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION)) + mode = (SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT); + else if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION)) + mode = SSL_VERIFY_PEER; + else + mode = SSL_VERIFY_NONE; + SSL_CTX_set_verify(soap->ctx, mode, soap->fsslverify); +#if (OPENSSL_VERSION_NUMBER < 0x00905100L) + SSL_CTX_set_verify_depth(soap->ctx, 1); +#else + SSL_CTX_set_verify_depth(soap->ctx, 9); +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static int +ssl_verify_callback(int ok, X509_STORE_CTX *store) +{ +#ifdef SOAP_DEBUG + if (!ok) + { char data[256]; + X509 *cert = X509_STORE_CTX_get_current_cert(store); + fprintf(stderr, "SSL verify error or warning with certificate at depth %d: %s\n", X509_STORE_CTX_get_error_depth(store), X509_verify_cert_error_string(X509_STORE_CTX_get_error(store))); + X509_NAME_oneline(X509_get_issuer_name(cert), data, sizeof(data)); + fprintf(stderr, "certificate issuer %s\n", data); + X509_NAME_oneline(X509_get_subject_name(cert), data, sizeof(data)); + fprintf(stderr, "certificate subject %s\n", data); + } +#endif + /* Note: return 1 to continue, but unsafe progress will be terminated by SSL */ + return ok; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_ssl_accept(struct soap *soap) +{ BIO *bio; + int timeouts, r, s; + if (!soap_valid_socket(soap->socket)) + return soap_set_receiver_error(soap, "SSL error", "No socket in soap_ssl_accept()", SOAP_SSL_ERROR); + if (!soap->ctx && (soap->error = soap->fsslauth(soap))) + return SOAP_INVALID_SOCKET; + if (!soap->ssl) + { soap->ssl = SSL_new(soap->ctx); + if (!soap->ssl) + return soap_set_receiver_error(soap, "SSL error", "SSL_new() failed in soap_ssl_accept()", SOAP_SSL_ERROR); + } + else + SSL_clear(soap->ssl); + soap->imode |= SOAP_ENC_SSL; + soap->omode |= SOAP_ENC_SSL; + /* Set SSL sockets to non-blocking */ +#if defined(WIN32) + { u_long nonblocking = 1; + ioctlsocket(soap->socket, FIONBIO, &nonblocking); + } +#elif defined(VXWORKS) + { u_long nonblocking = 1; + ioctl(soap->socket, FIONBIO, (int)&nonblocking); + } +#else + fcntl(soap->socket, F_SETFL, fcntl(soap->socket, F_GETFL)|O_NONBLOCK); +#endif + bio = BIO_new_socket(soap->socket, BIO_NOCLOSE); + SSL_set_bio(soap->ssl, bio, bio); + timeouts = 100; /* 10 sec retries, 100 times 0.1 sec */ + while ((r = SSL_accept(soap->ssl)) <= 0) + { int err = SSL_get_error(soap->ssl, r); + if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) + { struct timeval timeout; + fd_set fd; +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + return SOAP_FD_EXCEEDED; /* Hint: MUST increase FD_SETSIZE */ +#endif + timeout.tv_sec = 0; + timeout.tv_usec = 100000; + FD_ZERO(&fd); + FD_SET(soap->socket, &fd); + if (err == SSL_ERROR_WANT_READ) + s = select((int)soap->socket + 1, &fd, NULL, &fd, &timeout); + else + s = select((int)soap->socket + 1, NULL, &fd, &fd, &timeout); + if (s < 0 && (s = soap_socket_errno(soap->socket)) != SOAP_EINTR) + { soap->errnum = s; + break; + } + } + else + { soap->errnum = err; + break; + } + if (timeouts-- <= 0) + break; + } + if (r <= 0) + { soap_set_receiver_error(soap, soap_ssl_error(soap, r), "SSL_accept() failed in soap_ssl_accept()", SOAP_SSL_ERROR); + soap_closesock(soap); + return SOAP_SSL_ERROR; + } + if ((soap->ssl_flags & SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION)) + { X509 *peer; + int err; + if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK) + { soap_closesock(soap); + return soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL certificate presented by peer cannot be verified in soap_ssl_accept()", SOAP_SSL_ERROR); + } + peer = SSL_get_peer_certificate(soap->ssl); + if (!peer) + { soap_closesock(soap); + return soap_set_sender_error(soap, "SSL error", "No SSL certificate was presented by the peer in soap_ssl_accept()", SOAP_SSL_ERROR); + } + X509_free(peer); + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#endif /* WITH_OPENSSL */ + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_init(struct soap *soap) +{ soap->errmode = 1; +#ifdef WIN32 + if (tcp_done) + return 0; + else + { WSADATA w; + if (WSAStartup(MAKEWORD(1, 1), &w)) + return -1; + tcp_done = 1; + } +#endif + return 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_done(struct soap *soap) +{ +#ifdef SOAP_DEBUG + int i; +#endif + if (soap_check_state(soap)) + return; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Done with context\n")); + soap_free_temp(soap); + while (soap->clist) + { struct soap_clist *p = soap->clist->next; + SOAP_FREE(soap, soap->clist); + soap->clist = p; + } + soap->keep_alive = 0; /* to force close the socket */ + soap_closesock(soap); +#ifdef WITH_COOKIES + soap_free_cookies(soap); +#endif + while (soap->plugins) + { register struct soap_plugin *p = soap->plugins->next; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Removing plugin '%s'\n", soap->plugins->id)); + if (soap->plugins->fcopy || soap->state == SOAP_INIT) + soap->plugins->fdelete(soap, soap->plugins); + SOAP_FREE(soap, soap->plugins); + soap->plugins = p; + } + soap->fplugin = fplugin; + soap->fmalloc = NULL; +#ifndef WITH_NOHTTP + soap->fpost = http_post; + soap->fget = http_get; + soap->fform = NULL; + soap->fposthdr = http_post_header; + soap->fresponse = http_response; + soap->fparse = http_parse; + soap->fparsehdr = http_parse_header; +#endif + soap->fheader = NULL; +#ifndef WITH_NOIO +#ifndef WITH_IPV6 + soap->fresolve = tcp_gethost; +#else + soap->fresolve = NULL; +#endif + soap->faccept = tcp_accept; + soap->fopen = tcp_connect; + soap->fclose = tcp_disconnect; + soap->fclosesocket = tcp_closesocket; + soap->fshutdownsocket = tcp_shutdownsocket; + soap->fsend = fsend; + soap->frecv = frecv; + soap->fpoll = soap_poll; +#else + soap->fopen = NULL; + soap->fclose = NULL; + soap->fpoll = NULL; +#endif +#ifndef WITH_LEANER + soap->fprepareinit = NULL; + soap->fpreparesend = NULL; + soap->fpreparerecv = NULL; + soap->fpreparefinal = NULL; +#endif + soap->fseterror = NULL; + soap->fignore = NULL; + soap->fserveloop = NULL; +#ifdef WITH_OPENSSL + if (soap->session) + { SSL_SESSION_free(soap->session); + soap->session = NULL; + } +#endif + if (soap->state == SOAP_INIT) + { if (soap_valid_socket(soap->master)) + { soap->fclosesocket(soap, soap->master); + soap->master = SOAP_INVALID_SOCKET; + } +#ifdef WITH_OPENSSL + if (soap->ctx) + { SSL_CTX_free(soap->ctx); + soap->ctx = NULL; + } +#endif + } +#ifdef SOAP_DEBUG + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free logfiles\n")); + for (i = 0; i < SOAP_MAXLOGS; i++) + { if (soap->logfile[i]) + { SOAP_FREE(soap, (void*)soap->logfile[i]); + soap->logfile[i] = NULL; + } + soap_close_logfile(soap, i); + } + soap->state = 0; +#endif +#ifdef SOAP_MEM_DEBUG + soap_free_mht(soap); +#endif +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_cleanup(struct soap *soap) +{ soap_done(soap); +#ifdef WIN32 + if (!tcp_done) + return; + tcp_done = 0; + WSACleanup(); +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static const char* +tcp_error(struct soap *soap) +{ register const char *msg = NULL; + switch (soap->errmode) + { case 0: + msg = soap_strerror(soap); + break; + case 1: + msg = "WSAStartup failed"; + break; + case 2: + { +#ifndef WITH_LEAN + msg = soap_code_str(h_error_codes, soap->errnum); + if (!msg) +#endif + { sprintf(soap->msgbuf, "TCP/UDP IP error %d", soap->errnum); + msg = soap->msgbuf; + } + } + } + return msg; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static const char* +http_error(struct soap *soap, int status) +{ register const char *msg = SOAP_STR_EOS; +#ifndef WITH_LEAN + msg = soap_code_str(h_http_error_codes, status); + if (!msg) + msg = SOAP_STR_EOS; +#endif + return msg; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_IPV6 +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_gethost(struct soap *soap, const char *addr, struct in_addr *inaddr) +{ soap_int32 iadd = -1; + struct hostent hostent, *host = &hostent; +#ifdef VXWORKS + int hostint; + /* inet_addr(), and hostGetByName() expect "char *"; addr is a "const char *". */ + iadd = inet_addr((char*)addr); +#else +#if defined(_AIX43) || defined(TRU64) + struct hostent_data ht_data; +#endif +#ifdef AS400 + iadd = inet_addr((void*)addr); +#else + iadd = inet_addr(addr); +#endif +#endif + if (iadd != -1) + { memcpy(inaddr, &iadd, sizeof(iadd)); + return SOAP_OK; + } +#if defined(__GLIBC__) || (defined(HAVE_GETHOSTBYNAME_R) && (defined(FREEBSD) || defined(__FreeBSD__))) + if (gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &host, &soap->errnum) < 0) + host = NULL; +#elif defined(_AIX43) || defined(TRU64) + memset((void*)&ht_data, 0, sizeof(ht_data)); + if (gethostbyname_r(addr, &hostent, &ht_data) < 0) + { host = NULL; + soap->errnum = h_errno; + } +#elif defined(HAVE_GETHOSTBYNAME_R) + host = gethostbyname_r(addr, &hostent, soap->buf, SOAP_BUFLEN, &soap->errnum); +#elif defined(VXWORKS) + /* If the DNS resolver library resolvLib has been configured in the vxWorks + * image, a query for the host IP address is sent to the DNS server, if the + * name was not found in the local host table. */ + hostint = hostGetByName((char*)addr); + if (hostint == ERROR) + { host = NULL; + soap->errnum = soap_errno; + } +#else +#ifdef AS400 + if (!(host = gethostbyname((void*)addr))) + soap->errnum = h_errno; +#else + if (!(host = gethostbyname(addr))) + soap->errnum = h_errno; +#endif +#endif + if (!host) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Host name not found\n")); + return SOAP_ERR; + } +#ifdef VXWORKS + inaddr->s_addr = hostint; +#else + memcpy(inaddr, host->h_addr, host->h_length); +#endif + return SOAP_OK; +} +#endif +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static SOAP_SOCKET +tcp_connect(struct soap *soap, const char *endpoint, const char *host, int port) +{ +#ifdef WITH_IPV6 + struct addrinfo hints, *res, *ressave; +#endif + SOAP_SOCKET fd; + int err = 0; +#ifndef WITH_LEAN + int retry = 10; + int len = SOAP_BUFLEN; + int set = 1; +#endif + if (soap_valid_socket(soap->socket)) + soap->fclosesocket(soap, soap->socket); + soap->socket = SOAP_INVALID_SOCKET; + if (tcp_init(soap)) + { soap->errnum = 0; + soap_set_sender_error(soap, tcp_error(soap), "TCP init failed in tcp_connect()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + soap->errmode = 0; +#ifdef WITH_IPV6 + memset((void*)&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + hints.ai_socktype = SOCK_DGRAM; + else +#endif + hints.ai_socktype = SOCK_STREAM; + soap->errmode = 2; + if (soap->proxy_host) + err = getaddrinfo(soap->proxy_host, soap_int2s(soap, soap->proxy_port), &hints, &res); + else + err = getaddrinfo(host, soap_int2s(soap, port), &hints, &res); + if (err) + { soap_set_sender_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in tcp_connect()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + ressave = res; +again: + fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + soap->errmode = 0; +#else +#ifndef WITH_LEAN +again: +#endif +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + fd = socket(AF_INET, SOCK_DGRAM, 0); + else +#endif + fd = socket(AF_INET, SOCK_STREAM, 0); +#endif + if (!soap_valid_socket(fd)) + { soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "socket failed in tcp_connect()", SOAP_TCP_ERROR); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } +#ifdef SOCKET_CLOSE_ON_EXEC +#ifdef WIN32 +#ifndef UNDER_CE + SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0); +#endif +#else + fcntl(fd, F_SETFD, 1); +#endif +#endif +#ifndef WITH_LEAN + if (soap->connect_flags == SO_LINGER) + { struct linger linger; + memset((void*)&linger, 0, sizeof(linger)); + linger.l_onoff = 1; + linger.l_linger = 0; + if (setsockopt(fd, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger))) + { soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } + } + else if (soap->connect_flags && setsockopt(fd, SOL_SOCKET, soap->connect_flags, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "setsockopt failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } + if ((soap->keep_alive || soap->tcp_keep_alive) && setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } + if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } + if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } +#ifdef TCP_KEEPIDLE + if (soap->tcp_keep_idle && setsockopt((SOAP_SOCKET)fd, IPPROTO_TCP, TCP_KEEPIDLE, (unsigned int*)&(soap->tcp_keep_idle), sizeof(int))) + { soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPIDLE failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } +#endif +#ifdef TCP_KEEPINTVL + if (soap->tcp_keep_intvl && setsockopt((SOAP_SOCKET)fd, IPPROTO_TCP, TCP_KEEPINTVL, (unsigned int*)&(soap->tcp_keep_intvl), sizeof(int))) + { soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPINTVL failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } +#endif +#ifdef TCP_KEEPCNT + if (soap->tcp_keep_cnt && setsockopt((SOAP_SOCKET)fd, IPPROTO_TCP, TCP_KEEPCNT, (unsigned int*)&(soap->tcp_keep_cnt), sizeof(int))) + { soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_KEEPCNT failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, (SOAP_SOCKET)fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } +#endif +#ifdef TCP_NODELAY + if (!(soap->omode & SOAP_IO_UDP) && setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } +#endif +#endif + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Opening socket %d to host='%s' port=%d\n", fd, host, port)); +#ifndef WITH_IPV6 + soap->peerlen = sizeof(soap->peer); + memset((void*)&soap->peer, 0, sizeof(soap->peer)); + soap->peer.sin_family = AF_INET; + soap->errmode = 2; + if (soap->proxy_host) + { if (soap->fresolve(soap, soap->proxy_host, &soap->peer.sin_addr)) + { soap_set_sender_error(soap, tcp_error(soap), "get proxy host by name failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } + soap->peer.sin_port = htons((short)soap->proxy_port); + } + else + { if (soap->fresolve(soap, host, &soap->peer.sin_addr)) + { soap_set_sender_error(soap, tcp_error(soap), "get host by name failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } + soap->peer.sin_port = htons((short)port); + } + soap->errmode = 0; + if ((soap->omode & SOAP_IO_UDP)) + { +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return fd; + } +#endif +#ifndef WITH_LEAN + if (soap->connect_timeout) +#if defined(WIN32) + { u_long nonblocking = 1; + ioctlsocket(fd, FIONBIO, &nonblocking); + } +#elif defined(VXWORKS) + { u_long nonblocking = 1; + ioctl(fd, FIONBIO, (int)(&nonblocking)); /* modified to use fd */ + } +#else + fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)|O_NONBLOCK); +#endif + else +#if defined(WIN32) + { u_long blocking = 0; + ioctlsocket(fd, FIONBIO, &blocking); + } +#elif defined(VXWORKS) + { u_long blocking = 0; + ioctl(fd, FIONBIO, (int)(&blocking)); + } +#else + fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)&~O_NONBLOCK); +#endif +#endif + for (;;) + { +#ifdef WITH_IPV6 + if (connect(fd, res->ai_addr, (int)res->ai_addrlen)) +#else + if (connect(fd, (struct sockaddr*)&soap->peer, sizeof(soap->peer))) +#endif + { err = soap_socket_errno(fd); +#ifndef WITH_LEAN + if (err == SOAP_EADDRINUSE) + { soap->fclosesocket(soap, fd); + if (retry-- > 0) + goto again; + } + else if (soap->connect_timeout && (err == SOAP_EINPROGRESS || err == SOAP_EWOULDBLOCK)) + { + SOAP_SOCKLEN_T k; +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + { soap->error = SOAP_FD_EXCEEDED; +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; /* Hint: MUST increase FD_SETSIZE */ + } +#endif + for (;;) + { struct timeval timeout; + fd_set fds; + register int r; + if (soap->connect_timeout > 0) + { timeout.tv_sec = soap->connect_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->connect_timeout/1000000; + timeout.tv_usec = -soap->connect_timeout%1000000; + } + FD_ZERO(&fds); + FD_SET(fd, &fds); + r = select((int)fd + 1, NULL, &fds, NULL, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n")); + soap_set_sender_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } + r = soap_socket_errno(fd); + if (r != SOAP_EINTR) + { soap->errnum = r; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); + soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } + } + k = (SOAP_SOCKLEN_T)sizeof(soap->errnum); + if (!getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*)&soap->errnum, &k) && !soap->errnum) /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */ + break; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); + if (!soap->errnum) + soap->errnum = soap_socket_errno(fd); + soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } +#endif +#ifdef WITH_IPV6 + if (res->ai_next) + { res = res->ai_next; + soap->fclosesocket(soap, fd); + goto again; + } +#endif + if (err && err != SOAP_EINTR) + { soap->errnum = err; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not connect to host\n")); + soap_set_sender_error(soap, tcp_error(soap), "connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, fd); +#ifdef WITH_IPV6 + freeaddrinfo(ressave); +#endif + return SOAP_INVALID_SOCKET; + } + } + else + break; + } +#ifdef WITH_IPV6 + soap->peerlen = 0; /* IPv6: already connected so use send() */ + freeaddrinfo(ressave); +#endif +#ifndef WITH_LEAN + if (soap->connect_timeout) +#if defined(WIN32) + { u_long blocking = 0; + ioctlsocket(fd, FIONBIO, &blocking); + } +#elif defined(VXWORKS) + { u_long blocking = 0; + ioctl(fd, FIONBIO, (int)(&blocking)); + } +#else + fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)&~O_NONBLOCK); +#endif +#endif + soap->socket = fd; + soap->imode &= ~SOAP_ENC_SSL; + soap->omode &= ~SOAP_ENC_SSL; + if (!soap_tag_cmp(endpoint, "https:*")) + { +#ifdef WITH_OPENSSL + BIO *bio; + int r; + if (soap->proxy_host) + { unsigned int k = soap->omode; /* make sure we only parse HTTP */ + size_t n = soap->count; /* save the content length */ + char *userid, *passwd; + soap->omode &= ~SOAP_ENC; /* mask IO and ENC */ + soap->omode |= SOAP_IO_BUFFER; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connecting to %s proxy server\n", soap->proxy_http_version)); + sprintf(soap->tmpbuf, "CONNECT %s:%d HTTP/%s", host, port, soap->proxy_http_version); + if (soap_begin_send(soap) + || (soap->error = soap->fposthdr(soap, soap->tmpbuf, NULL))) + { soap->fclosesocket(soap, fd); + return SOAP_INVALID_SOCKET; + } +#ifndef WITH_LEAN + if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761) + { sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd); + strcpy(soap->tmpbuf, "Basic "); + soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262)); + if ((soap->error = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf))) + { soap->fclosesocket(soap, fd); + return soap->error; + } + } +#endif + if ((soap->error = soap->fposthdr(soap, NULL, NULL)) + || soap_flush(soap)) + { soap->fclosesocket(soap, fd); + return SOAP_INVALID_SOCKET; + } + soap->omode = k; + k = soap->imode; + soap->imode &= ~SOAP_ENC; /* mask IO and ENC */ + userid = soap->userid; /* preserve */ + passwd = soap->passwd; /* preserve */ + if ((soap->error = soap->fparse(soap))) + { soap->fclosesocket(soap, fd); + return SOAP_INVALID_SOCKET; + } + soap->userid = userid; /* restore */ + soap->passwd = passwd; /* restore */ + soap->imode = k; /* restore */ + soap->count = n; /* restore */ + if (soap_begin_send(soap)) + { soap->fclosesocket(soap, fd); + return SOAP_INVALID_SOCKET; + } + if (endpoint) + strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint)-1); /* restore */ + } + if (!soap->ctx && (soap->error = soap->fsslauth(soap))) + { soap_set_sender_error(soap, "SSL error", "SSL authentication failed in tcp_connect(): check password, key file, and ca file.", SOAP_SSL_ERROR); + soap->fclosesocket(soap, fd); + return SOAP_INVALID_SOCKET; + } + soap->ssl = SSL_new(soap->ctx); + if (!soap->ssl) + { soap->fclosesocket(soap, fd); + soap->error = SOAP_SSL_ERROR; + return SOAP_INVALID_SOCKET; + } + if (soap->session) + { if (!strcmp(soap->session_host, host) && soap->session_port == port) + SSL_set_session(soap->ssl, soap->session); + SSL_SESSION_free(soap->session); + soap->session = NULL; + } + soap->imode |= SOAP_ENC_SSL; + soap->omode |= SOAP_ENC_SSL; + bio = BIO_new_socket(fd, BIO_NOCLOSE); + SSL_set_bio(soap->ssl, bio, bio); + /* Connect timeout: set SSL sockets to non-blocking */ +#ifndef WITH_LEAN + if (soap->connect_timeout) +#if defined(WIN32) + { u_long nonblocking = 1; + ioctlsocket(fd, FIONBIO, &nonblocking); + } +#elif defined(VXWORKS) + { u_long nonblocking = 1; + ioctl(fd, FIONBIO, (int)(&nonblocking)); + } +#else + fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)|O_NONBLOCK); +#endif +#endif + /* Try connecting until success or timeout */ + for (;;) + { if ((r = SSL_connect(soap->ssl)) <= 0) + { int err = SSL_get_error(soap->ssl, r); + if (err != SSL_ERROR_NONE && err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE) + { soap_set_sender_error(soap, soap_ssl_error(soap, r), "SSL connect failed in tcp_connect()", SOAP_SSL_ERROR); + soap->fclosesocket(soap, fd); + return SOAP_INVALID_SOCKET; + } + if (soap->connect_timeout) + { +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + { soap->error = SOAP_FD_EXCEEDED; + return SOAP_INVALID_SOCKET; /* Hint: MUST increase FD_SETSIZE */ + } +#endif + for (;;) + { struct timeval timeout; + fd_set fds; + register int r; + if (soap->connect_timeout > 0) + { timeout.tv_sec = soap->connect_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->connect_timeout/1000000; + timeout.tv_usec = -soap->connect_timeout%1000000; + } + FD_ZERO(&fds); + FD_SET(fd, &fds); + r = select((int)fd + 1, &fds, NULL, &fds, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connect timeout\n")); + soap_set_sender_error(soap, "Timeout", "connect failed in tcp_connect()", SOAP_TCP_ERROR); + soap->fclosesocket(soap, fd); + return SOAP_INVALID_SOCKET; + } + } + continue; + } + } + break; + } + /* Set SSL sockets to non-blocking */ +#ifndef WITH_LEAN +#if defined(WIN32) + { u_long nonblocking = 1; + ioctlsocket(fd, FIONBIO, &nonblocking); + } +#elif defined(VXWORKS) + { u_long nonblocking = 1; + ioctl(fd, FIONBIO, (int)(&nonblocking)); + } +#else + fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)|O_NONBLOCK); +#endif +#endif + /* Check server credentials when required */ + if ((soap->ssl_flags & SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION)) + { int err; + if ((err = SSL_get_verify_result(soap->ssl)) != X509_V_OK) + { soap_set_sender_error(soap, X509_verify_cert_error_string(err), "SSL certificate presented by peer cannot be verified in tcp_connect()", SOAP_SSL_ERROR); + soap->fclosesocket(soap, fd); + return SOAP_INVALID_SOCKET; + } + if (!(soap->ssl_flags & SOAP_SSL_SKIP_HOST_CHECK)) + { X509_NAME *subj; + int ext_count; + int ok = 0; + X509 *peer; + peer = SSL_get_peer_certificate(soap->ssl); + if (!peer) + { soap_set_sender_error(soap, "SSL error", "No SSL certificate was presented by the peer in tcp_connect()", SOAP_SSL_ERROR); + soap->fclosesocket(soap, fd); + return SOAP_INVALID_SOCKET; + } + ext_count = X509_get_ext_count(peer); + if (ext_count > 0) + { int i; + for (i = 0; i < ext_count; i++) + { X509_EXTENSION *ext = X509_get_ext(peer, i); + const char *ext_str = OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext))); + if (ext_str && !strcmp(ext_str, "subjectAltName")) + { X509V3_EXT_METHOD *meth = X509V3_EXT_get(ext); + void *ext_data; +#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) + const unsigned char *data; +#else + unsigned char *data; +#endif + STACK_OF(CONF_VALUE) *val; + int j; + if (!meth) + break; + data = ext->value->data; +#if (OPENSSL_VERSION_NUMBER > 0x00907000L) + if (meth->it) + ext_data = ASN1_item_d2i(NULL, &data, ext->value->length, ASN1_ITEM_ptr(meth->it)); + else + { /* OpenSSL not perfectly portable at this point (?): + Some compilers appear to prefer + meth->d2i(NULL, (const unsigned char**)&data, ... + or + meth->d2i(NULL, &data, ext->value->length); + */ + ext_data = meth->d2i(NULL, &data, ext->value->length); + } +#else + ext_data = meth->d2i(NULL, &data, ext->value->length); +#endif + val = meth->i2v(meth, ext_data, NULL); + for (j = 0; j < sk_CONF_VALUE_num(val); j++) + { CONF_VALUE *nval = sk_CONF_VALUE_value(val, j); + if (nval && !strcmp(nval->name, "DNS") && !strcmp(nval->value, host)) + { ok = 1; + break; + } + } + } + if (ok) + break; + } + } + if (!ok && (subj = X509_get_subject_name(peer))) + { int i = -1; + do + { ASN1_STRING *name; + i = X509_NAME_get_index_by_NID(subj, NID_commonName, i); + if (i == -1) + break; + name = X509_NAME_ENTRY_get_data(X509_NAME_get_entry(subj, i)); + if (name) + { if (!soap_tag_cmp(host, (const char*)name)) + ok = 1; + else + { unsigned char *tmp = NULL; + ASN1_STRING_to_UTF8(&tmp, name); + if (tmp) + { if (!soap_tag_cmp(host, (const char*)tmp)) + ok = 1; + OPENSSL_free(tmp); + } + } + } + } while (!ok); + } + X509_free(peer); + if (!ok) + { soap_set_sender_error(soap, "SSL error", "SSL certificate host name mismatch in tcp_connect()", SOAP_SSL_ERROR); + soap->fclosesocket(soap, fd); + return SOAP_INVALID_SOCKET; + } + } + } +#else + soap->fclosesocket(soap, fd); + soap->error = SOAP_SSL_ERROR; + return SOAP_INVALID_SOCKET; +#endif + } + return fd; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +SOAP_FMAC1 +SOAP_SOCKET +SOAP_FMAC2 +soap_bind(struct soap *soap, const char *host, int port, int backlog) +{ +#ifdef WITH_IPV6 + struct addrinfo *addrinfo = NULL; + struct addrinfo hints; + struct addrinfo res; + int err; +#endif +#ifndef WITH_LEAN + int len = SOAP_BUFLEN; + int set = 1; +#endif + if (soap_valid_socket(soap->master)) + { soap->fclosesocket(soap, soap->master); + soap->master = SOAP_INVALID_SOCKET; + } + soap->socket = SOAP_INVALID_SOCKET; + soap->errmode = 1; + if (tcp_init(soap)) + { soap_set_receiver_error(soap, tcp_error(soap), "TCP init failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#ifdef WITH_IPV6 + memset((void*)&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + hints.ai_socktype = SOCK_DGRAM; + else +#endif + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_PASSIVE; + soap->errmode = 2; + err = getaddrinfo(host, soap_int2s(soap, port), &hints, &addrinfo); + if (addrinfo) + { res = *addrinfo; + memcpy(&soap->peer, addrinfo->ai_addr, addrinfo->ai_addrlen); + soap->peerlen = addrinfo->ai_addrlen; + res.ai_addr = (struct sockaddr*)&soap->peer; + res.ai_addrlen = soap->peerlen; + freeaddrinfo(addrinfo); + } + if (err || !addrinfo) + { soap_set_receiver_error(soap, SOAP_GAI_STRERROR(err), "getaddrinfo failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + soap->master = (int)socket(res.ai_family, res.ai_socktype, res.ai_protocol); +#else +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + soap->master = (int)socket(AF_INET, SOCK_DGRAM, 0); + else +#endif + soap->master = (int)socket(AF_INET, SOCK_STREAM, 0); +#endif + soap->errmode = 0; + if (!soap_valid_socket(soap->master)) + { soap->errnum = soap_socket_errno(soap->master); + soap_set_receiver_error(soap, tcp_error(soap), "socket failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + soap->socket = soap->master; +#endif +#ifdef SOCKET_CLOSE_ON_EXEC +#ifdef WIN32 +#ifndef UNDER_CE + SetHandleInformation((HANDLE)soap->master, HANDLE_FLAG_INHERIT, 0); +#endif +#else + fcntl(soap->master, F_SETFD, 1); +#endif +#endif +#ifndef WITH_LEAN + if (soap->bind_flags && setsockopt(soap->master, SOL_SOCKET, soap->bind_flags, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->master); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt(soap->master, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->master); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + if (setsockopt(soap->master, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->master); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + if (setsockopt(soap->master, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->master); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#ifdef TCP_NODELAY + if (!(soap->omode & SOAP_IO_UDP) && setsockopt(soap->master, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->master); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#endif +#endif +#ifdef WITH_IPV6 + soap->errmode = 0; + if (bind(soap->master, res.ai_addr, (int)res.ai_addrlen)) + { soap->errnum = soap_socket_errno(soap->master); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n")); + soap_closesock(soap); + soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#else + soap->peerlen = sizeof(soap->peer); + memset((void*)&soap->peer, 0, sizeof(soap->peer)); + soap->peer.sin_family = AF_INET; + soap->errmode = 2; + if (host) + { if (soap->fresolve(soap, host, &soap->peer.sin_addr)) + { soap_set_receiver_error(soap, tcp_error(soap), "get host by name failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + } + else + soap->peer.sin_addr.s_addr = htonl(INADDR_ANY); + soap->peer.sin_port = htons((short)port); + soap->errmode = 0; + if (bind(soap->master, (struct sockaddr*)&soap->peer, (int)soap->peerlen)) + { soap->errnum = soap_socket_errno(soap->master); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n")); + soap_closesock(soap); + soap_set_receiver_error(soap, tcp_error(soap), "bind failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +#endif + if (!(soap->omode & SOAP_IO_UDP) && listen(soap->master, backlog)) + { soap->errnum = soap_socket_errno(soap->master); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not bind to host\n")); + soap_closesock(soap); + soap_set_receiver_error(soap, tcp_error(soap), "listen failed in soap_bind()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + return soap->master; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_poll(struct soap *soap) +{ +#ifndef WITH_LEAN + struct timeval timeout; + fd_set rfd, sfd, xfd; + register int r; +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + return SOAP_FD_EXCEEDED; /* Hint: MUST increase FD_SETSIZE */ +#endif + timeout.tv_sec = 0; + timeout.tv_usec = 0; + FD_ZERO(&rfd); + FD_ZERO(&sfd); + FD_ZERO(&xfd); + if (soap_valid_socket(soap->socket)) + { FD_SET(soap->socket, &rfd); + FD_SET(soap->socket, &sfd); + FD_SET(soap->socket, &xfd); + r = select((int)soap->socket + 1, &rfd, &sfd, &xfd, &timeout); + if (r > 0 && FD_ISSET(soap->socket, &xfd)) + r = -1; + } + else if (soap_valid_socket(soap->master)) + { FD_SET(soap->master, &sfd); + r = select((int)soap->master + 1, NULL, &sfd, NULL, &timeout); + } + else + return SOAP_OK; + if (r > 0) + { +#ifdef WITH_OPENSSL + if (soap->imode & SOAP_ENC_SSL) + { + if (soap_valid_socket(soap->socket) + && FD_ISSET(soap->socket, &sfd) + && (!FD_ISSET(soap->socket, &rfd) + || SSL_peek(soap->ssl, soap->tmpbuf, 1) > 0)) + return SOAP_OK; + } + else +#endif + if (soap_valid_socket(soap->socket) + && FD_ISSET(soap->socket, &sfd) + && (!FD_ISSET(soap->socket, &rfd) + || recv(soap->socket, soap->tmpbuf, 1, MSG_PEEK) > 0)) + return SOAP_OK; + } + else if (r < 0) + { soap->errnum = soap_socket_errno(soap->master); + if ((soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) && soap_socket_errno(soap->master) != SOAP_EINTR) + { soap_set_receiver_error(soap, tcp_error(soap), "select failed in soap_poll()", SOAP_TCP_ERROR); + return soap->error = SOAP_TCP_ERROR; + } + } + else + soap->errnum = 0; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Polling: other end down on socket=%d select=%d\n", soap->socket, r)); + return SOAP_EOF; +#else + return SOAP_OK; +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static SOAP_SOCKET +tcp_accept(struct soap *soap, SOAP_SOCKET s, struct sockaddr *a, int *n) +{ SOAP_SOCKET fd; + fd = accept(s, a, (SOAP_SOCKLEN_T*)n); /* portability note: see SOAP_SOCKLEN_T definition in stdsoap2.h */ +#ifdef SOCKET_CLOSE_ON_EXEC +#ifdef WIN32 +#ifndef UNDER_CE + SetHandleInformation((HANDLE)fd, HANDLE_FLAG_INHERIT, 0); +#endif +#else + fcntl(fd, F_SETFD, FD_CLOEXEC); +#endif +#endif + return fd; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +SOAP_FMAC1 +SOAP_SOCKET +SOAP_FMAC2 +soap_accept(struct soap *soap) +{ int n = (int)sizeof(soap->peer); +#ifndef WITH_LEAN + int len = SOAP_BUFLEN; + int set = 1; +#endif + soap->error = SOAP_OK; +#ifdef WITH_UDP + if ((soap->omode & SOAP_IO_UDP)) + return soap->socket = soap->master; +#endif + memset((void*)&soap->peer, 0, sizeof(soap->peer)); + soap->socket = SOAP_INVALID_SOCKET; + soap->errmode = 0; + soap->keep_alive = 0; + if (soap_valid_socket(soap->master)) + { register int err; + for (;;) + { +#ifndef WITH_LEAN + if (soap->accept_timeout) + { +#ifndef WIN32 + if ((int)soap->socket >= (int)FD_SETSIZE) + { soap->error = SOAP_FD_EXCEEDED; + return SOAP_INVALID_SOCKET; /* Hint: MUST increase FD_SETSIZE */ + } +#endif + for (;;) + { struct timeval timeout; + fd_set fd; + register int r; + if (soap->accept_timeout > 0) + { timeout.tv_sec = soap->accept_timeout; + timeout.tv_usec = 0; + } + else + { timeout.tv_sec = -soap->accept_timeout/1000000; + timeout.tv_usec = -soap->accept_timeout%1000000; + } + FD_ZERO(&fd); + FD_SET(soap->master, &fd); + r = select((int)soap->master + 1, &fd, &fd, &fd, &timeout); + if (r > 0) + break; + if (!r) + { soap->errnum = 0; + soap_set_receiver_error(soap, "Timeout", "accept failed in soap_accept()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + r = soap_socket_errno(soap->master); + if (r != SOAP_EINTR) + { soap->errnum = r; + soap_closesock(soap); + soap_set_sender_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } + } +#if defined(WIN32) + { u_long nonblocking = 1; + ioctlsocket(soap->master, FIONBIO, &nonblocking); + } +#elif defined(VXWORKS) + { u_long nonblocking = 1; + ioctl(soap->master, FIONBIO, (int)(&nonblocking)); + } +#else + fcntl(soap->master, F_SETFL, fcntl(soap->master, F_GETFL)|O_NONBLOCK); +#endif + } + else +#if defined(WIN32) + { u_long blocking = 0; + ioctlsocket(soap->master, FIONBIO, &blocking); + } +#elif defined(VXWORKS) + { u_long blocking = 0; + ioctl(soap->master, FIONBIO, (int)(&blocking)); + } +#else + fcntl(soap->master, F_SETFL, fcntl(soap->master, F_GETFL)&~O_NONBLOCK); +#endif +#endif + soap->socket = soap->faccept(soap, soap->master, (struct sockaddr*)&soap->peer, &n); + soap->peerlen = (size_t)n; + if (soap_valid_socket(soap->socket)) + { +#ifdef WITH_IPV6 +/* Use soap->host to store the numeric form of the remote host */ + getnameinfo((struct sockaddr*)&soap->peer, n, soap->host, sizeof(soap->host), NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket %d from %s\n", soap->socket, soap->host)); + soap->ip = 0; /* info stored in soap->peer and soap->host */ + soap->port = 0; /* info stored in soap->peer and soap->host */ +#else + soap->ip = ntohl(soap->peer.sin_addr.s_addr); + soap->port = (int)ntohs(soap->peer.sin_port); /* does not return port number on some systems */ + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept socket %d at port %d from IP %d.%d.%d.%d\n", soap->socket, soap->port, (int)(soap->ip>>24)&0xFF, (int)(soap->ip>>16)&0xFF, (int)(soap->ip>>8)&0xFF, (int)soap->ip&0xFF)); +#endif +#ifndef WITH_LEAN + if (soap->accept_flags == SO_LINGER) + { struct linger linger; + memset((void*)&linger, 0, sizeof(linger)); + linger.l_onoff = 1; + linger.l_linger = 0; + if (setsockopt(soap->socket, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(struct linger))) + { soap->errnum = soap_socket_errno(soap->socket); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_LINGER failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } + } + else if (soap->accept_flags && setsockopt(soap->socket, SOL_SOCKET, soap->accept_flags, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->socket); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } + if (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) && setsockopt(soap->socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->socket); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_KEEPALIVE failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } + if (setsockopt(soap->socket, SOL_SOCKET, SO_SNDBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->socket); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_SNDBUF failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } + if (setsockopt(soap->socket, SOL_SOCKET, SO_RCVBUF, (char*)&len, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->socket); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt SO_RCVBUF failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } +#ifdef TCP_NODELAY + if (!(soap->omode & SOAP_IO_UDP) && setsockopt(soap->socket, IPPROTO_TCP, TCP_NODELAY, (char*)&set, sizeof(int))) + { soap->errnum = soap_socket_errno(soap->socket); + soap_set_receiver_error(soap, tcp_error(soap), "setsockopt TCP_NODELAY failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } +#endif +#endif + if (soap->accept_timeout) + { +#if defined(WIN32) + u_long blocking = 0; + ioctlsocket(soap->master, FIONBIO, &blocking); + ioctlsocket(soap->socket, FIONBIO, &blocking); +#elif defined(VXWORKS) + u_long blocking = 0; + ioctl(soap->master, FIONBIO, (int)(&blocking)); + ioctl(soap->socket, FIONBIO, (int)(&blocking)); +#elif defined(PALM) + fcntl(soap->master, F_SETFL, fcntl(soap->master, F_GETFL,0)&~O_NONBLOCK); + fcntl(soap->socket, F_SETFL, fcntl(soap->socket, F_GETFL,0)&~O_NONBLOCK); +#elif defined(SYMBIAN) + long blocking = 0; + ioctl(soap->master, 0/*FIONBIO*/, &blocking); +#else + fcntl(soap->master, F_SETFL, fcntl(soap->master, F_GETFL)&~O_NONBLOCK); + fcntl(soap->socket, F_SETFL, fcntl(soap->socket, F_GETFL)&~O_NONBLOCK); +#endif + } + soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0); + return soap->socket; + } + err = soap_socket_errno(soap->socket); + if (err != 0 && err != SOAP_EINTR && err != SOAP_EAGAIN) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Accept failed from %s\n", soap->host)); + soap->errnum = err; + soap_set_receiver_error(soap, tcp_error(soap), "accept failed in soap_accept()", SOAP_TCP_ERROR); + soap_closesock(soap); + return SOAP_INVALID_SOCKET; + } + } + } + else + { soap->errnum = 0; + soap_set_receiver_error(soap, tcp_error(soap), "no master socket in soap_accept()", SOAP_TCP_ERROR); + return SOAP_INVALID_SOCKET; + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_disconnect(struct soap *soap) +{ +#ifdef WITH_OPENSSL + if (soap->ssl) + { int r, s = 0; + if (soap->session) + { SSL_SESSION_free(soap->session); + soap->session = NULL; + } + if (*soap->host) + { soap->session = SSL_get1_session(soap->ssl); + if (soap->session) + { strcpy(soap->session_host, soap->host); + soap->session_port = soap->port; + } + } + r = SSL_shutdown(soap->ssl); + if (r == 0) + { if (soap_valid_socket(soap->socket)) + { struct timeval timeout; + fd_set fd; + if (soap->fshutdownsocket(soap, soap->socket, 1)) + { /* + wait up to 10 seconds for close_notify to be sent by peer (if peer not + present, this avoids calling SSL_shutdown() which has a lengthy return + timeout) + */ +#ifndef WIN32 + if ((int)soap->socket < (int)FD_SETSIZE) + { +#endif + timeout.tv_sec = 10; + timeout.tv_usec = 0; + FD_ZERO(&fd); + FD_SET(soap->socket, &fd); + r = select((int)soap->socket + 1, &fd, NULL, &fd, &timeout); + if (r <= 0 && soap_socket_errno(soap->socket) != SOAP_EINTR) + { soap->errnum = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Connection lost...\n")); + soap->fclosesocket(soap, soap->socket); + soap->socket = SOAP_INVALID_SOCKET; + SSL_free(soap->ssl); + soap->ssl = NULL; + ERR_remove_state(0); + return SOAP_OK; + } +#ifndef WIN32 + } +#endif + } + } + r = SSL_shutdown(soap->ssl); + } + if (r != 1) + { s = ERR_get_error(); + if (s) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown failed: %d\n", SSL_get_error(soap->ssl, r))); + if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP)) + { soap->fclosesocket(soap, soap->socket); + soap->socket = SOAP_INVALID_SOCKET; + } + SSL_free(soap->ssl); + soap->ssl = NULL; + ERR_remove_state(0); + return SOAP_SSL_ERROR; + } + } + SSL_free(soap->ssl); + soap->ssl = NULL; + ERR_remove_state(0); + } +#endif + if (soap_valid_socket(soap->socket) && !(soap->omode & SOAP_IO_UDP)) + { soap->fshutdownsocket(soap, soap->socket, 2); + soap->fclosesocket(soap, soap->socket); + soap->socket = SOAP_INVALID_SOCKET; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_closesocket(struct soap *soap, SOAP_SOCKET fd) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Close socket %d\n", (int)fd)); + return soap_closesocket(fd); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static int +tcp_shutdownsocket(struct soap *soap, SOAP_SOCKET fd, int how) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Shutdown socket %d how=%d\n", (int)fd, how)); + return shutdown(fd, how); +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_closesock(struct soap *soap) +{ register int status = soap->error; + if (status == SOAP_EOF || status == SOAP_TCP_ERROR || status == SOAP_SSL_ERROR || !soap->keep_alive) + { if (soap->fclose && (soap->error = soap->fclose(soap))) + return soap->error; + soap->keep_alive = 0; + } +#ifdef WITH_ZLIB + if (soap->zlib_state == SOAP_ZLIB_DEFLATE) + deflateEnd(&soap->d_stream); + else if (soap->zlib_state == SOAP_ZLIB_INFLATE) + inflateEnd(&soap->d_stream); + soap->zlib_state = SOAP_ZLIB_NONE; +#endif + return soap->error = status; +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_hash(register const char *s) +{ register size_t h = 0; + while (*s) + h = 65599*h + *s++; + return h % SOAP_IDHASH; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static void +soap_init_pht(struct soap *soap) +{ register int i; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing pointer hashtable\n")); + soap->pblk = NULL; + soap->pidx = 0; + for (i = 0; i < (int)SOAP_PTRHASH; i++) + soap->pht[i] = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_new1(soap_mode mode) +{ return soap_new2(mode, mode); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_new() +{ return soap_new2(SOAP_IO_DEFAULT, SOAP_IO_DEFAULT); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_new2(soap_mode imode, soap_mode omode) +{ struct soap *soap = (struct soap*)malloc(sizeof(struct soap)); + if (soap) + soap_init2(soap, imode, omode); + return soap; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_free(struct soap *soap) +{ soap_done(soap); + free(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_del(struct soap *soap) +{ free(soap); +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static void +soap_free_pht(struct soap *soap) +{ register struct soap_pblk *pb, *next; + register int i; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free pointer hashtable\n")); + for (pb = soap->pblk; pb; pb = next) + { next = pb->next; + SOAP_FREE(soap, pb); + } + soap->pblk = NULL; + soap->pidx = 0; + for (i = 0; i < (int)SOAP_PTRHASH; i++) + soap->pht[i] = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_embed(struct soap *soap, const void *p, const struct soap_array *a, int n, const char *tag, int type) +{ register int i; + struct soap_plist *pp; + if (soap->version != 1) + soap->encoding = 1; + if (a) + i = soap_array_pointer_lookup(soap, p, a, n, type, &pp); + else + i = soap_pointer_lookup(soap, p, type, &pp); + if (i) + { if (soap_is_embedded(soap, pp) + || soap_is_single(soap, pp)) + return 0; + soap_set_embedded(soap, pp); + } + return i; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_pointer_lookup(struct soap *soap, const void *p, int type, struct soap_plist **ppp) +{ register struct soap_plist *pp; + *ppp = NULL; + if (p) + { for (pp = soap->pht[soap_hash_ptr(p)]; pp; pp = pp->next) + { if (pp->ptr == p && pp->type == type) + { *ppp = pp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d id=%d\n", p, type, pp->id)); + return pp->id; + } + } + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup location=%p type=%d: not found\n", p, type)); + return 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_pointer_enter(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp) +{ register size_t h; + register struct soap_plist *pp; + if (!soap->pblk || soap->pidx >= SOAP_PTRBLK) + { register struct soap_pblk *pb = (struct soap_pblk*)SOAP_MALLOC(soap, sizeof(struct soap_pblk)); + if (!pb) + { soap->error = SOAP_EOM; + return 0; + } + pb->next = soap->pblk; + soap->pblk = pb; + soap->pidx = 0; + } + *ppp = pp = &soap->pblk->plist[soap->pidx++]; + if (a) + h = soap_hash_ptr(a->__ptr); + else + h = soap_hash_ptr(p); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Pointer enter location=%p array=%p size=%d dim=%d type=%d id=%d\n", p, a?a->__ptr:NULL, a?a->__size:0, n, type, soap->idnum+1)); + pp->next = soap->pht[h]; + pp->type = type; + pp->mark1 = 0; + pp->mark2 = 0; + pp->ptr = p; + pp->array = a; + soap->pht[h] = pp; + pp->id = ++soap->idnum; + return pp->id; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_array_pointer_lookup(struct soap *soap, const void *p, const struct soap_array *a, int n, int type, struct soap_plist **ppp) +{ register struct soap_plist *pp; + *ppp = NULL; + if (!p || !a->__ptr) + return 0; + for (pp = soap->pht[soap_hash_ptr(a->__ptr)]; pp; pp = pp->next) + { if (pp->type == type && pp->array && pp->array->__ptr == a->__ptr) + { register int i; + for (i = 0; i < n; i++) + if (((const int*)&pp->array->__size)[i] != ((const int*)&a->__size)[i]) + break; + if (i == n) + { *ppp = pp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d id=%d\n", a->__ptr, type, pp->id)); + return pp->id; + } + } + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array lookup location=%p type=%d: not found\n", a->__ptr, type)); + return 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_begin_count(struct soap *soap) +{ +#ifndef WITH_LEANER + if ((soap->mode & SOAP_ENC_DIME) || (soap->omode & SOAP_ENC_DIME)) + soap->mode = soap->omode | SOAP_IO_LENGTH | SOAP_ENC_DIME; + else +#endif + { soap->mode = soap->omode; + if ((soap->mode & SOAP_IO) == SOAP_IO_STORE + || (((soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_ENC_XML)) +#ifndef WITH_LEANER + && !soap->fpreparesend +#endif + )) + soap->mode &= ~SOAP_IO_LENGTH; + else + soap->mode |= SOAP_IO_LENGTH; + } +#ifdef WITH_ZLIB + if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH) + { if (!(soap->mode & SOAP_ENC_DIME)) + soap->mode &= ~SOAP_IO_LENGTH; + if (soap->mode & SOAP_ENC_XML) + soap->mode |= SOAP_IO_BUFFER; + else + soap->mode |= SOAP_IO_STORE; + } +#endif + if (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH)) + soap->mode |= SOAP_XML_TREE; +#ifndef WITH_LEANER + if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME)) + soap->mode |= SOAP_ENC_MIME; + else + soap->mode &= ~SOAP_ENC_MTOM; + if (soap->mode & SOAP_ENC_MIME) + soap_select_mime_boundary(soap); + soap->dime.list = soap->dime.last; /* keep track of last DIME attachment */ +#endif + soap->count = 0; + soap->ns = 0; + soap->null = 0; + soap->position = 0; + soap->mustUnderstand = 0; + soap->encoding = 0; + soap->part = SOAP_BEGIN; + soap->idnum = 0; + soap_clr_attr(soap); + soap_set_local_namespaces(soap); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin count phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count)); +#ifndef WITH_LEANER + soap->dime.count = 0; /* count # of attachments */ + soap->dime.size = 0; /* accumulate total size of attachments */ + if (soap->fprepareinit && (soap->mode & SOAP_IO) != SOAP_IO_STORE) + return soap->error = soap->fprepareinit(soap); +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_end_count(struct soap *soap) +{ +#ifndef WITH_LEANER + if (soap->fpreparefinal) + return soap->error = soap->fpreparefinal(soap); +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of count phase\n")); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_begin_send(struct soap *soap) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing for output\n")); + soap->error = SOAP_OK; + soap->mode = soap->omode | (soap->mode & (SOAP_IO_LENGTH | SOAP_ENC_DIME)); +#ifdef WITH_ZLIB + if ((soap->mode & SOAP_ENC_ZLIB) && (soap->mode & SOAP_IO) == SOAP_IO_FLUSH) + { if (soap->mode & SOAP_ENC_XML) + soap->mode |= SOAP_IO_BUFFER; + else + soap->mode |= SOAP_IO_STORE; + } +#endif +#ifdef WITH_UDP + if ((soap->mode & SOAP_IO_UDP)) + { soap->mode |= SOAP_ENC_XML; + if (soap->count > SOAP_BUFLEN) + return soap->error = SOAP_UDP_ERROR; + } +#endif + if ((soap->mode & SOAP_IO) == SOAP_IO_FLUSH && soap_valid_socket(soap->socket)) + { if (soap->count || (soap->mode & SOAP_IO_LENGTH) || (soap->mode & SOAP_ENC_XML)) + soap->mode |= SOAP_IO_BUFFER; + else + soap->mode |= SOAP_IO_STORE; + } + soap->mode &= ~SOAP_IO_LENGTH; + if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) + soap_new_block(soap); + if (!(soap->mode & SOAP_IO_KEEPALIVE)) + soap->keep_alive = 0; + if (!soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH)) + soap->mode |= SOAP_XML_TREE; +#ifndef WITH_LEANER + if ((soap->mode & SOAP_ENC_MTOM) && (soap->mode & SOAP_ENC_DIME)) + { soap->mode |= SOAP_ENC_MIME; + soap->mode &= ~SOAP_ENC_DIME; + } + else + soap->mode &= ~SOAP_ENC_MTOM; + if (soap->mode & SOAP_ENC_MIME) + soap_select_mime_boundary(soap); +#ifdef WIN32 +#ifndef UNDER_CE +#ifndef WITH_FASTCGI + if (!soap_valid_socket(soap->socket)) /* Set win32 stdout or soap->sendfd to BINARY, e.g. to support DIME */ +#ifdef __BORLANDC__ + setmode(soap->sendfd, O_BINARY); +#else + _setmode(soap->sendfd, _O_BINARY); +#endif +#endif +#endif +#endif +#endif + if (soap->mode & SOAP_IO) + { soap->bufidx = 0; + soap->buflen = 0; + } + soap->chunksize = 0; + soap->ns = 0; + soap->null = 0; + soap->position = 0; + soap->mustUnderstand = 0; + soap->encoding = 0; + soap->idnum = 0; + soap->level = 0; + soap_clr_attr(soap); + soap_set_local_namespaces(soap); +#ifdef WITH_ZLIB + soap->z_ratio_out = 1.0; + if ((soap->mode & SOAP_ENC_ZLIB) && soap->zlib_state != SOAP_ZLIB_DEFLATE) + { soap->d_stream.next_out = (Byte*)soap->z_buf; + soap->d_stream.avail_out = SOAP_BUFLEN; +#ifdef WITH_GZIP + if (soap->zlib_out != SOAP_ZLIB_DEFLATE) + { memcpy(soap->z_buf, "\37\213\10\0\0\0\0\0\0\377", 10); + soap->d_stream.next_out = (Byte*)soap->z_buf + 10; + soap->d_stream.avail_out = SOAP_BUFLEN - 10; + soap->z_crc = crc32(0L, NULL, 0); + soap->zlib_out = SOAP_ZLIB_GZIP; + if (deflateInit2(&soap->d_stream, soap->z_level, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; + } + else +#endif + if (deflateInit(&soap->d_stream, soap->z_level) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflate initialized\n")); + soap->zlib_state = SOAP_ZLIB_DEFLATE; + } +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin send phase (socket=%d mode=0x%x count=%lu)\n", soap->socket, soap->mode, (unsigned long)soap->count)); + soap->part = SOAP_BEGIN; +#ifndef WITH_LEANER + if (soap->fprepareinit && (soap->mode & SOAP_IO) == SOAP_IO_STORE) + soap->fprepareinit(soap); +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_embedded(struct soap *soap, const void *p, int t) +{ struct soap_plist *pp; + if (soap_pointer_lookup(soap, p, t, &pp)) + { pp->mark1 = 1; + pp->mark2 = 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded %p type=%d mark set to 1\n", p, t)); + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_reference(struct soap *soap, const void *p, int t) +{ struct soap_plist *pp; + if (!p || (soap->mode & SOAP_XML_TREE)) + return 1; + if (soap_pointer_lookup(soap, p, t, &pp)) + { if (pp->mark1 == 0) + { pp->mark1 = 2; + pp->mark2 = 2; + } + } + else if (soap_pointer_enter(soap, p, NULL, 0, t, &pp)) + { pp->mark1 = 0; + pp->mark2 = 0; + } + else + return 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reference %p type=%d (%d %d)\n", p, t, (int)pp->mark1, (int)pp->mark2)); + return pp->mark1; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_array_reference(struct soap *soap, const void *p, const struct soap_array *a, int n, int t) +{ register int i; + struct soap_plist *pp; + if (!p || !a->__ptr) + return 1; + i = soap_array_pointer_lookup(soap, p, a, n, t, &pp); + if (i) + { if (pp->mark1 == 0) + { pp->mark1 = 2; + pp->mark2 = 2; + } + } + else if (!soap_pointer_enter(soap, p, a, n, t, &pp)) + return 1; + else + { pp->mark1 = 0; + pp->mark2 = 0; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Array reference %p ptr=%p dim=%d type=%d (%d %d)\n", p, a->__ptr, n, t, (int)pp->mark1, (int)pp->mark2)); + return pp->mark1; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_embedded_id(struct soap *soap, int id, const void *p, int t) +{ struct soap_plist *pp = NULL; + if (soap->mode & SOAP_XML_TREE) + return id; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id %p type=%d id=%d\n", p, t, id)); + if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER) + { if (id < 0) + { id = soap_pointer_lookup(soap, p, t, &pp); + if (id) + { if (soap->mode & SOAP_IO_LENGTH) + pp->mark1 = 2; + else + pp->mark2 = 2; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id multiref id=%d %p type=%d = (%d %d)\n", id, p, t, (int)pp->mark1, (int)pp->mark2)); + } + return -1; + } + return id; + } + if (id < 0) + id = soap_pointer_lookup(soap, p, t, &pp); + else if (id && !soap_pointer_lookup(soap, p, t, &pp)) + return 0; + if (id && pp) + { if (soap->mode & SOAP_IO_LENGTH) + pp->mark1 = 1; + else + pp->mark2 = 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Embedded_id embedded ref id=%d %p type=%d = (%d %d)\n", id, p, t, (int)pp->mark1, (int)pp->mark2)); + } + return id; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_is_embedded(struct soap *soap, struct soap_plist *pp) +{ if (!pp) + return 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Is embedded? %d %d\n", (int)pp->mark1, (int)pp->mark2)); + if (soap->version == 1 && soap->encodingStyle && !(soap->mode & SOAP_XML_GRAPH) && soap->part != SOAP_IN_HEADER) + { if (soap->mode & SOAP_IO_LENGTH) + return pp->mark1 != 0; + return pp->mark2 != 0; + } + if (soap->mode & SOAP_IO_LENGTH) + return pp->mark1 == 1; + return pp->mark2 == 1; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_is_single(struct soap *soap, struct soap_plist *pp) +{ if (soap->part == SOAP_IN_HEADER) + return 1; + if (!pp) + return 0; + if (soap->mode & SOAP_IO_LENGTH) + return pp->mark1 == 0; + return pp->mark2 == 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_embedded(struct soap *soap, struct soap_plist *pp) +{ if (!pp) + return; + if (soap->mode & SOAP_IO_LENGTH) + pp->mark1 = 1; + else + pp->mark2 = 1; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_attachment(struct soap *soap, const char *tag, int id, const void *p, const struct soap_array *a, const char *aid, const char *atype, const char *aoptions, int n, const char *type, int t) +{ +#ifndef WITH_NOIDREF + struct soap_plist *pp; + int i; + if (!p || !a->__ptr || (!aid && !atype)) + return soap_element_id(soap, tag, id, p, a, n, type, t); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Attachment tag='%s' id='%s' (%d) type='%s'\n", tag, aid?aid:"", id, atype?atype:"")); + i = soap_array_pointer_lookup(soap, p, a, n, t, &pp); + if (!i) + { i = soap_pointer_enter(soap, p, a, n, t, &pp); + if (!i) + { soap->error = SOAP_EOM; + return -1; + } + } + if (id <= 0) + id = i; + if (!aid) + { sprintf(soap->tmpbuf, soap->dime_id_format, id); + aid = soap_strdup(soap, soap->tmpbuf); + } + /* Add MTOM xop:Include element when necessary */ + /* TODO: this code to be obsoleted with new import/xop.h conventions */ + if ((soap->mode & SOAP_ENC_MTOM) && strcmp(tag, "xop:Include")) + { if (soap_element_begin_out(soap, tag, 0, type) + || soap_element_href(soap, "xop:Include", 0, "href", aid) + || soap_element_end_out(soap, tag)) + return soap->error; + } + else if (soap_element_href(soap, tag, 0, "href", aid)) + return soap->error; + if (soap->mode & SOAP_IO_LENGTH) + { if (pp->mark1 != 3) + { struct soap_multipart *content; + if (soap->mode & SOAP_ENC_MTOM) + content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, (char*)a->__ptr, a->__size); + else + content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, (char*)a->__ptr, a->__size); + if (!content) + { soap->error = SOAP_EOM; + return -1; + } + if (!strncmp(aid, "cid:", 4)) /* RFC 2111 */ + { if (soap->mode & SOAP_ENC_MTOM) + { char *s = (char*)soap_malloc(soap, strlen(aid) - 1); + if (s) + { *s = '<'; + strcpy(s + 1, aid + 4); + strcat(s, ">"); + content->id = s; + } + } + else + content->id = aid + 4; + } + else + content->id = aid; + content->type = atype; + content->options = aoptions; + content->encoding = SOAP_MIME_BINARY; + pp->mark1 = 3; + } + } + else + pp->mark2 = 3; +#endif + return -1; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static void +soap_init_iht(struct soap *soap) +{ register int i; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing ID hashtable\n")); + for (i = 0; i < SOAP_IDHASH; i++) + soap->iht[i] = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_1 +static void +soap_free_iht(struct soap *soap) +{ register int i; + register struct soap_ilist *ip = NULL, *p = NULL; + register struct soap_flist *fp = NULL, *fq = NULL; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free ID hashtable\n")); + for (i = 0; i < SOAP_IDHASH; i++) + { for (ip = soap->iht[i]; ip; ip = p) + { for (fp = ip->flist; fp; fp = fq) + { fq = fp->next; + SOAP_FREE(soap, fp); + } + p = ip->next; + SOAP_FREE(soap, ip); + } + soap->iht[i] = NULL; + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +struct soap_ilist * +SOAP_FMAC2 +soap_lookup(struct soap *soap, const char *id) +{ register struct soap_ilist *ip = NULL; + for (ip = soap->iht[soap_hash(id)]; ip; ip = ip->next) + if (!strcmp(ip->id, id)) + return ip; + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +struct soap_ilist * +SOAP_FMAC2 +soap_enter(struct soap *soap, const char *id) +{ register size_t h; + register struct soap_ilist *ip; + ip = (struct soap_ilist*)SOAP_MALLOC(soap, sizeof(struct soap_ilist) + strlen(id)); + if (ip) + { h = soap_hash(id); + strcpy(ip->id, id); + ip->next = soap->iht[h]; + soap->iht[h] = ip; + return ip; + } + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_malloc(struct soap *soap, size_t n) +{ register char *p; + if (!n) + return (void*)SOAP_NON_NULL; + if (!soap) + return SOAP_MALLOC(soap, n); + if (soap->fmalloc) + p = (char*)soap->fmalloc(soap, n); + else + { n += sizeof(short); + n += (-(long)n) & (sizeof(void*)-1); /* align at 4-, 8- or 16-byte boundary */ + if (!(p = (char*)SOAP_MALLOC(soap, n + sizeof(void*) + sizeof(size_t)))) + { soap->error = SOAP_EOM; + return NULL; + } + /* set the canary to detect corruption */ + *(short*)(p + n - sizeof(short)) = (short)SOAP_CANARY; + /* keep chain of alloced cells for destruction */ + *(void**)(p + n) = soap->alist; + *(size_t*)(p + n + sizeof(void*)) = n; + soap->alist = p + n; + } + soap->alloced = 1; + return p; +} +#endif + +/******************************************************************************/ +#ifdef SOAP_MEM_DEBUG +static void +soap_init_mht(struct soap *soap) +{ register int i; + for (i = 0; i < (int)SOAP_PTRHASH; i++) + soap->mht[i] = NULL; +} +#endif + +/******************************************************************************/ +#ifdef SOAP_MEM_DEBUG +static void +soap_free_mht(struct soap *soap) +{ register int i; + register struct soap_mlist *mp, *mq; + for (i = 0; i < (int)SOAP_PTRHASH; i++) + { for (mp = soap->mht[i]; mp; mp = mq) + { mq = mp->next; + if (mp->live) + fprintf(stderr, "%s(%d): malloc() = %p not freed (memory leak or forgot to call soap_end()?)\n", mp->file, mp->line, mp->ptr); + free(mp); + } + soap->mht[i] = NULL; + } +} +#endif + +/******************************************************************************/ +#ifdef SOAP_MEM_DEBUG +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_track_malloc(struct soap *soap, const char *file, int line, size_t size) +{ register void *p = malloc(size); + if (soap) + { register size_t h = soap_hash_ptr(p); + register struct soap_mlist *mp = (struct soap_mlist*)malloc(sizeof(struct soap_mlist)); + if (soap->fdebug[SOAP_INDEX_TEST]) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): malloc(%lu) = %p\n", file, line, (unsigned long)size, p)); + } + mp->next = soap->mht[h]; + mp->ptr = p; + mp->file = file; + mp->line = line; + mp->live = 1; + soap->mht[h] = mp; + } + return p; +} +#endif + +/******************************************************************************/ +#ifdef SOAP_MEM_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_track_free(struct soap *soap, const char *file, int line, void *p) +{ register size_t h = soap_hash_ptr(p); + register struct soap_mlist *mp; + for (mp = soap->mht[h]; mp; mp = mp->next) + if (mp->ptr == p) + break; + if (mp) + { if (mp->live) + { free(p); + if (soap->fdebug[SOAP_INDEX_TEST]) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): free(%p)\n", file, line, p)); + } + mp->live = 0; + } + else + fprintf(stderr, "%s(%d): free(%p) double free of pointer malloced at %s(%d)\n", file, line, p, mp->file, mp->line); + } + else + fprintf(stderr, "%s(%d): free(%p) pointer not malloced\n", file, line, p); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_MEM_DEBUG +static void +soap_track_unlink(struct soap *soap, const void *p) +{ register size_t h = soap_hash_ptr(p); + register struct soap_mlist *mp; + for (mp = soap->mht[h]; mp; mp = mp->next) + if (mp->ptr == p) + break; + if (mp) + mp->live = 0; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_dealloc(struct soap *soap, void *p) +{ if (soap_check_state(soap)) + return; + if (p) + { register char **q; + for (q = (char**)&soap->alist; *q; q = *(char***)q) + { + if (*(short*)(char*)(*q - sizeof(short)) != (short)SOAP_CANARY) + { +#ifdef SOAP_MEM_DEBUG + fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n"); +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n")); + DBGHEX(TEST, *q - 200, 200); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n")); + soap->error = SOAP_MOE; + return; + } + if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*)))) + { *q = **(char***)q; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Freed data at %p\n", p)); + SOAP_FREE(soap, p); + return; + } + } + soap_delete(soap, p); + } + else + { register char *q; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free all soap_malloc() data\n")); + while (soap->alist) + { q = (char*)soap->alist; + if (*(short*)(char*)(q - sizeof(short)) != (short)SOAP_CANARY) + { +#ifdef SOAP_MEM_DEBUG + fprintf(stderr, "Data corruption in dynamic allocation (see logs)\n"); +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Data corruption:\n")); + DBGHEX(TEST, q - 200, 200); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\n")); + soap->error = SOAP_MOE; + return; + } + soap->alist = *(void**)q; + q -= *(size_t*)(q + sizeof(void*)); + SOAP_FREE(soap, q); + } + /* we must assume these were deallocated: */ + soap->action = NULL; + soap->fault = NULL; + soap->header = NULL; + soap->userid = NULL; + soap->passwd = NULL; + soap->authrealm = NULL; + soap->http_content = NULL; +#ifndef WITH_LEANER + soap_clr_mime(soap); +#endif + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_delete(struct soap *soap, void *p) +{ register struct soap_clist **cp; + if (soap_check_state(soap)) + return; + cp = &soap->clist; + if (p) + { while (*cp) + { if (p == (*cp)->ptr) + { register struct soap_clist *q = *cp; + *cp = q->next; + if (q->fdelete(q)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: deletion callback failed for object type %d\n", q->ptr, q->type)); +#ifdef SOAP_MEM_DEBUG + fprintf(stderr, "new(object type = %d) = %p not freed: deletion callback failed\n", q->type, q->ptr); +#endif + } + SOAP_FREE(soap, q); + return; + } + cp = &(*cp)->next; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: address not in list\n", p)); + } + else + { while (*cp) + { register struct soap_clist *q = *cp; + *cp = q->next; + if (q->fdelete(q)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not dealloc data %p: deletion callback failed for object type %d\n", q->ptr, q->type)); +#ifdef SOAP_MEM_DEBUG + fprintf(stderr, "new(object type = %d) = %p not freed: deletion callback failed\n", q->type, q->ptr); +#endif + } + SOAP_FREE(soap, q); + } + } + soap->fault = NULL; /* this was possibly deallocated */ + soap->header = NULL; /* this was possibly deallocated */ +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +struct soap_clist * +SOAP_FMAC2 +soap_link(struct soap *soap, void *p, int t, int n, int (*fdelete)(struct soap_clist*)) +{ register struct soap_clist *cp; + if ((cp = (struct soap_clist*)SOAP_MALLOC(soap, sizeof(struct soap_clist)))) + { cp->next = soap->clist; + cp->type = t; + cp->size = n; + cp->ptr = p; + cp->fdelete = fdelete; + soap->clist = cp; + } + return cp; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_unlink(struct soap *soap, const void *p) +{ register char **q; + register struct soap_clist **cp; + if (!soap || !p) + return; + for (q = (char**)&soap->alist; *q; q = *(char***)q) + { if (p == (void*)(*q - *(size_t*)(*q + sizeof(void*)))) + { *q = **(char***)q; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked data %p\n", p)); +#ifdef SOAP_MEM_DEBUG + soap_track_unlink(soap, p); +#endif + return; + } + } + for (cp = &soap->clist; *cp; cp = &(*cp)->next) + { if (p == (*cp)->ptr) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unlinked class instance %p\n", p)); + q = (char**)*cp; + *cp = (*cp)->next; + SOAP_FREE(soap, q); + return; + } + } +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_lookup_type(struct soap *soap, const char *id) +{ register struct soap_ilist *ip; + if (id && *id) + { ip = soap_lookup(soap, id); + if (ip) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Lookup id='%s' type=%d\n", id, ip->type)); + return ip->type; + } + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "lookup type id='%s' NOT FOUND! Need to get it from xsi:type\n", id)); + return 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_id_lookup(struct soap *soap, const char *id, void **p, int t, size_t n, unsigned int k) +{ struct soap_ilist *ip; + void **q; + if (!p || !id || !*id) + return p; + ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */ + if (!ip) + { ip = soap_enter(soap, id); /* new hash table entry for string id */ + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding first href='%s' type=%d %p (%u bytes)\n", id, t, p, (unsigned int)n)); + ip->type = t; + ip->size = n; + ip->link = p; + ip->copy = NULL; + ip->flist = NULL; + ip->ptr = NULL; + ip->level = k; + *p = NULL; + } + else if (ip->ptr) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolved href='%s' type=%d location=%p (%u bytes)\n", id, t, ip->ptr, (unsigned int)n)); + if (ip->type != t) + { strcpy(soap->id, id); + soap->error = SOAP_HREF; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility: href='%s' id-type=%d href-type=%d\n", id, ip->type, t)); + return NULL; + } + while (ip->level < k) + { q = (void**)soap_malloc(soap, sizeof(void*)); + if (!q) + return NULL; + *p = (void*)q; + p = q; + k--; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); + } + *p = ip->ptr; + } + else if (ip->level > k) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving level %u pointers to href='%s'\n", ip->level, id)); + while (ip->level > k) + { void *s, **r = &ip->link; + q = (void**)ip->link; + while (q) + { *r = (void*)soap_malloc(soap, sizeof(void*)); + s = *q; + *q = *r; + r = (void**)*r; + q = (void**)s; + } + *r = NULL; + ip->size = n; + ip->copy = NULL; + ip->level = ip->level - 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); + } + q = (void**)ip->link; + ip->link = p; + *p = (void*)q; + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarded href='%s' type=%d location=%p (%u bytes)\n", id, t, p, (unsigned int)n)); + while (ip->level < k) + { q = (void**)soap_malloc(soap, sizeof(void*)); + *p = q; + p = q; + k--; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Descending one level...\n")); + } + q = (void**)ip->link; + ip->link = p; + *p = (void*)q; + } + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIDREF +#ifndef PALM_2 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_id_forward(struct soap *soap, const char *href, void *p, size_t len, int st, int tt, size_t n, unsigned int k, void (*fcopy)(struct soap*, int, int, void*, size_t, const void*, size_t)) +{ struct soap_ilist *ip; + if (!p || !href || !*href) + return p; + ip = soap_lookup(soap, href); /* lookup pointer to hash table entry for string id */ + if (!ip) + { ip = soap_enter(soap, href); /* new hash table entry for string id */ + ip->type = st; + ip->size = n; + ip->link = NULL; + ip->copy = NULL; + ip->ptr = NULL; + ip->level = 0; + ip->flist = NULL; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "New entry href='%s' type=%d size=%lu level=%d location=%p\n", href, st, (unsigned long)n, k, p)); + } + else if (ip->type != st || (ip->level == k && ip->size != n)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n", href, ip->type, (unsigned long)ip->size, k, st, (unsigned long)n)); + strcpy(soap->id, href); + soap->error = SOAP_HREF; + return NULL; + } + if (fcopy || n < sizeof(void*) || *href != '#') + { register struct soap_flist *fp = (struct soap_flist*)SOAP_MALLOC(soap, sizeof(struct soap_flist)); + if (!fp) + { soap->error = SOAP_EOM; + return NULL; + } + fp->next = ip->flist; + fp->type = tt; + fp->ptr = p; + fp->level = k; + fp->len = len; + if (fcopy) + fp->fcopy = fcopy; + else + fp->fcopy = soap_fcopy; + ip->flist = fp; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding type=%d (target type=%d) size=%lu location=%p level=%u len=%lu href='%s'\n", st, tt, (unsigned long)n, p, k, (unsigned long)len, href)); + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Forwarding copying address %p for type=%d href='%s'\n", p, st, href)); + *(void**)p = ip->copy; + ip->copy = p; + } + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void* +SOAP_FMAC2 +soap_id_enter(struct soap *soap, const char *id, void *p, int t, size_t n, unsigned int k, const char *type, const char *arrayType, void *(*finstantiate)(struct soap*, int, const char*, const char*, size_t*)) +{ +#ifndef WITH_NOIDREF + struct soap_ilist *ip; +#endif + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Enter id='%s' type=%d loc=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k)); + soap->alloced = 0; + if (!p) + { if (finstantiate) + p = finstantiate(soap, t, type, arrayType, &n); + else + p = soap_malloc(soap, n); + if (p) + soap->alloced = 1; + } +#ifndef WITH_NOIDREF + if (!id || !*id) +#endif + return p; +#ifndef WITH_NOIDREF + ip = soap_lookup(soap, id); /* lookup pointer to hash table entry for string id */ + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Lookup entry id='%s for location=%p'\n", id, p)); + if (!ip) + { ip = soap_enter(soap, id); /* new hash table entry for string id */ + ip->type = t; + ip->link = NULL; + ip->copy = NULL; + ip->flist = NULL; + ip->size = n; + ip->ptr = p; + ip->level = k; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "New entry id='%s' type=%d size=%lu level=%u location=%p\n", id, t, (unsigned long)n, k, p)); + } + else if ((ip->type != t || (ip->level == k && ip->size != n)) && (ip->copy || ip->flist)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Type incompatibility id='%s' expect type=%d size=%lu level=%u got type=%d size=%lu\n", id, ip->type, (unsigned long)ip->size, k, t, (unsigned long)n)); + strcpy(soap->id, id); + soap->error = SOAP_HREF; + return NULL; + } + else if (ip->ptr) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Multiply defined id='%s'\n", id)); + strcpy(soap->id, id); + soap->error = SOAP_DUPLICATE_ID; + return NULL; + } + else + { ip->size = n; + ip->ptr = p; + ip->level = k; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Update entry id='%s' type=%d location=%p size=%lu level=%u\n", id, t, p, (unsigned long)n, k)); + } + return ip->ptr; +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_fcopy(struct soap *soap, int st, int tt, void *p, size_t len, const void *q, size_t n) +{ DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Copying data type=%d (target type=%d) %p -> %p (%lu bytes)\n", st, tt, q, p, (unsigned long)n)); + memcpy(p, q, n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_end_send(struct soap *soap) +{ +#ifndef WITH_LEANER + if (soap->dime.list) + { /* SOAP body referenced attachments must appear first */ + soap->dime.last->next = soap->dime.first; + soap->dime.first = soap->dime.list->next; + soap->dime.list->next = NULL; + soap->dime.last = soap->dime.list; + } + if (soap_putdime(soap) || soap_putmime(soap)) + return soap->error; + soap->mime.list = NULL; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->dime.list = NULL; + soap->dime.first = NULL; + soap->dime.last = NULL; +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End send\n")); + if (soap->mode & SOAP_IO) /* need to flush the remaining data in buffer */ + { if (soap_flush(soap)) +#ifdef WITH_ZLIB + { if (soap->mode & SOAP_ENC_ZLIB && soap->zlib_state == SOAP_ZLIB_DEFLATE) + { soap->zlib_state = SOAP_ZLIB_NONE; + deflateEnd(&soap->d_stream); + } + return soap->error; + } +#else + return soap->error; +#endif +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { int r; + soap->d_stream.avail_in = 0; + do + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflating remainder\n")); + r = deflate(&soap->d_stream, Z_FINISH); + if (soap->d_stream.avail_out != SOAP_BUFLEN) + { if (soap_flush_raw(soap, soap->z_buf, SOAP_BUFLEN - soap->d_stream.avail_out)) + { soap->zlib_state = SOAP_ZLIB_NONE; + deflateEnd(&soap->d_stream); + return soap->error; + } + soap->d_stream.next_out = (Byte*)soap->z_buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + } + } while (r == Z_OK); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Deflated %lu->%lu bytes\n", soap->d_stream.total_in, soap->d_stream.total_out)); + soap->z_ratio_out = (float)soap->d_stream.total_out / (float)soap->d_stream.total_in; + soap->mode &= ~SOAP_ENC_ZLIB; + soap->zlib_state = SOAP_ZLIB_NONE; + if (deflateEnd(&soap->d_stream) != Z_OK || r != Z_STREAM_END) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Unable to end deflate: %s\n", soap->d_stream.msg?soap->d_stream.msg:"")); + return soap->error = SOAP_ZLIB_ERROR; + } +#ifdef WITH_GZIP + if (soap->zlib_out != SOAP_ZLIB_DEFLATE) + { soap->z_buf[0] = soap->z_crc & 0xFF; + soap->z_buf[1] = (soap->z_crc >> 8) & 0xFF; + soap->z_buf[2] = (soap->z_crc >> 16) & 0xFF; + soap->z_buf[3] = (soap->z_crc >> 24) & 0xFF; + soap->z_buf[4] = soap->d_stream.total_in & 0xFF; + soap->z_buf[5] = (soap->d_stream.total_in >> 8) & 0xFF; + soap->z_buf[6] = (soap->d_stream.total_in >> 16) & 0xFF; + soap->z_buf[7] = (soap->d_stream.total_in >> 24) & 0xFF; + if (soap_flush_raw(soap, soap->z_buf, 8)) + return soap->error; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip crc32=%lu\n", (unsigned long)soap->z_crc)); + } +#endif + } +#endif + if ((soap->mode & SOAP_IO) == SOAP_IO_STORE) + { char *p; +#ifndef WITH_NOHTTP + if (!(soap->mode & SOAP_ENC_XML)) + { soap->mode--; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending buffered message of length %u\n", (unsigned int)soap->blist->size)); + if (soap->status >= SOAP_POST) + soap->error = soap->fpost(soap, soap->endpoint, soap->host, soap->port, soap->path, soap->action, soap->blist->size); + else if (soap->status != SOAP_STOP) + soap->error = soap->fresponse(soap, soap->status, soap->blist->size); + if (soap->error || soap_flush(soap)) + return soap->error; + soap->mode++; + } +#endif + for (p = soap_first_block(soap); p; p = soap_next_block(soap)) + { DBGMSG(SENT, p, soap_block_size(soap)); + if ((soap->error = soap->fsend(soap, p, soap_block_size(soap)))) + { soap_end_block(soap); + return soap->error; + } + } + soap_end_block(soap); + } +#ifndef WITH_LEANER + else if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) + { DBGMSG(SENT, "\r\n0\r\n\r\n", 7); + if ((soap->error = soap->fsend(soap, "\r\n0\r\n\r\n", 7))) + return soap->error; + } +#endif + } +#ifdef WITH_TCPFIN +#ifdef WITH_OPENSSL + if (!soap->ssl && soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP)) + soap->fshutdownsocket(soap, soap->socket, 1); /* Send TCP FIN */ +#else + if (soap_valid_socket(soap->socket) && !soap->keep_alive && !(soap->omode & SOAP_IO_UDP)) + soap->fshutdownsocket(soap, soap->socket, 1); /* Send TCP FIN */ +#endif +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End of send phase\n")); + soap->omode &= ~SOAP_XML_SEC; + soap->count = 0; + soap->part = SOAP_END; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_end_recv(struct soap *soap) +{ soap->part = SOAP_END; +#ifndef WITH_LEANER + if ((soap->mode & SOAP_ENC_DIME) && soap_getdime(soap)) + { soap->dime.first = NULL; + soap->dime.last = NULL; + return soap->error; + } + soap->dime.list = soap->dime.first; + soap->dime.first = NULL; + soap->dime.last = NULL; + /* Check if MIME attachments and mime-post-check flag is set, if set call soap_resolve() and return */ + if (soap->mode & SOAP_ENC_MIME) + { +#ifndef WITH_NOIDREF + if (soap->mode & SOAP_MIME_POSTCHECK) + { soap_resolve(soap); + return SOAP_OK; + } +#endif + if (soap_getmime(soap)) + return soap->error; + } + soap->mime.list = soap->mime.first; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = NULL; + if (soap->xlist) + { struct soap_multipart *content; + for (content = soap->mime.list; content; content = content->next) + soap_resolve_attachment(soap, content); + } +#endif + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "End of receive message ok\n")); +#ifdef WITH_ZLIB + if (soap->mode & SOAP_ENC_ZLIB) + { /* Make sure end of compressed content is reached */ + while (soap->d_stream.next_out != Z_NULL) + if ((int)soap_get1(soap) == EOF) + break; + soap->mode &= ~SOAP_ENC_ZLIB; + memcpy(soap->buf, soap->z_buf, SOAP_BUFLEN); + soap->bufidx = (char*)soap->d_stream.next_in - soap->z_buf; + soap->buflen = soap->z_buflen; + soap->zlib_state = SOAP_ZLIB_NONE; + if (inflateEnd(&soap->d_stream) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Inflate end ok\n")); +#ifdef WITH_GZIP + if (soap->zlib_in == SOAP_ZLIB_GZIP) + { soap_wchar c; + short i; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Inflate gzip crc check\n")); + for (i = 0; i < 8; i++) + { if ((int)(c = soap_get1(soap)) == EOF) + return soap->error = SOAP_EOF; + soap->z_buf[i] = (char)c; + } + if (soap->z_crc != ((uLong)(unsigned char)soap->z_buf[0] | ((uLong)(unsigned char)soap->z_buf[1] << 8) | ((uLong)(unsigned char)soap->z_buf[2] << 16) | ((uLong)(unsigned char)soap->z_buf[3] << 24))) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: crc check failed, message corrupted? (crc32=%lu)\n", (unsigned long)soap->z_crc)); + return soap->error = SOAP_ZLIB_ERROR; + } + if (soap->d_stream.total_out != ((uLong)(unsigned char)soap->z_buf[4] | ((uLong)(unsigned char)soap->z_buf[5] << 8) | ((uLong)(unsigned char)soap->z_buf[6] << 16) | ((uLong)(unsigned char)soap->z_buf[7] << 24))) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Gzip error: incorrect message length\n")); + return soap->error = SOAP_ZLIB_ERROR; + } + } + soap->zlib_in = SOAP_ZLIB_NONE; +#endif + } +#endif + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) + while ((int)soap_getchar(soap) != EOF) /* advance to last chunk */ + ; + if (soap->fdisconnect && (soap->error = soap->fdisconnect(soap))) + return soap->error; +#ifndef WITH_NOIDREF + if (soap_resolve(soap)) + return soap->error; +#endif +#ifndef WITH_LEANER + if (soap->xlist) + { if (soap->mode & SOAP_ENC_MTOM) + return soap->error = SOAP_MIME_HREF; + return soap->error = SOAP_DIME_HREF; + } +#endif + soap_free_temp(soap); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_free_temp(struct soap *soap) +{ register struct soap_nlist *np, *nq; + register struct soap_attribute *tp, *tq; + register struct Namespace *ns; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free namespace stack\n")); + for (np = soap->nlist; np; np = nq) + { nq = np->next; + SOAP_FREE(soap, np); + } + soap->nlist = NULL; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free any remaining temp blocks\n")); + while (soap->blist) + soap_end_block(soap); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute storage\n")); + for (tp = soap->attributes; tp; tp = tq) + { tq = tp->next; + if (tp->value) + SOAP_FREE(soap, tp->value); + SOAP_FREE(soap, tp); + } + soap->attributes = NULL; +#ifdef WITH_FAST + if (soap->labbuf) + SOAP_FREE(soap, soap->labbuf); + soap->labbuf = NULL; + soap->lablen = 0; + soap->labidx = 0; +#endif + ns = soap->local_namespaces; + if (ns) + { for (; ns->id; ns++) + { if (ns->out) + { if (soap->encodingStyle == ns->out) + soap->encodingStyle = SOAP_STR_EOS; + SOAP_FREE(soap, ns->out); + ns->out = NULL; + } + if (soap->encodingStyle == ns->ns) + soap->encodingStyle = SOAP_STR_EOS; + } + SOAP_FREE(soap, soap->local_namespaces); + soap->local_namespaces = NULL; + } +#ifndef WITH_LEANER + while (soap->xlist) + { struct soap_xlist *xp = soap->xlist->next; + SOAP_FREE(soap, soap->xlist); + soap->xlist = xp; + } +#endif +#ifndef WITH_NOIDREF + soap_free_pht(soap); + soap_free_iht(soap); +#endif +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +static void +soap_init_logs(struct soap *soap) +{ int i; + for (i = 0; i < SOAP_MAXLOGS; i++) + { soap->logfile[i] = NULL; + soap->fdebug[i] = NULL; + } +} +#endif + +/******************************************************************************/ +#if !defined(WITH_LEAN) || defined(SOAP_DEBUG) +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_open_logfile(struct soap *soap, int i) +{ if (soap->logfile[i]) + soap->fdebug[i] = fopen(soap->logfile[i], i < 2 ? "ab" : "a"); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +static void +soap_close_logfile(struct soap *soap, int i) +{ if (soap->fdebug[i]) + { fclose(soap->fdebug[i]); + soap->fdebug[i] = NULL; + } +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_close_logfiles(struct soap *soap) +{ int i; + for (i = 0; i < SOAP_MAXLOGS; i++) + soap_close_logfile(soap, i); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +static void +soap_set_logfile(struct soap *soap, int i, const char *logfile) +{ const char *s; + char *t = NULL; + soap_close_logfile(soap, i); + s = soap->logfile[i]; + soap->logfile[i] = logfile; + if (s) + SOAP_FREE(soap, (void*)s); + if (logfile) + if ((t = (char*)SOAP_MALLOC(soap, strlen(logfile) + 1))) + strcpy(t, logfile); + soap->logfile[i] = t; +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_recv_logfile(struct soap *soap, const char *logfile) +{ soap_set_logfile(soap, SOAP_INDEX_RECV, logfile); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_sent_logfile(struct soap *soap, const char *logfile) +{ soap_set_logfile(soap, SOAP_INDEX_SENT, logfile); +} +#endif + +/******************************************************************************/ +#ifdef SOAP_DEBUG +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_test_logfile(struct soap *soap, const char *logfile) +{ soap_set_logfile(soap, SOAP_INDEX_TEST, logfile); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_copy(struct soap *soap) +{ return soap_copy_context((struct soap*)malloc(sizeof(struct soap)), soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +struct soap* +SOAP_FMAC2 +soap_copy_context(struct soap *copy, struct soap *soap) +{ if (soap_check_state(soap)) + return NULL; + if (copy) + { register struct soap_plugin *p = NULL; + memcpy(copy, soap, sizeof(struct soap)); + copy->state = SOAP_COPY; + copy->error = SOAP_OK; + copy->userid = NULL; + copy->passwd = NULL; + copy->nlist = NULL; + copy->blist = NULL; + copy->clist = NULL; + copy->alist = NULL; + copy->attributes = NULL; + copy->labbuf = NULL; + copy->lablen = 0; + copy->labidx = 0; +#ifdef SOAP_MEM_DEBUG + soap_init_mht(copy); +#endif +#ifdef SOAP_DEBUG + soap_init_logs(copy); + soap_set_recv_logfile(copy, soap->logfile[SOAP_INDEX_RECV]); + soap_set_sent_logfile(copy, soap->logfile[SOAP_INDEX_SENT]); + soap_set_test_logfile(copy, soap->logfile[SOAP_INDEX_TEST]); +#endif + copy->local_namespaces = NULL; +#ifndef WITH_NOIDREF + soap_init_iht(copy); + soap_init_pht(copy); +#endif + copy->header = NULL; + copy->fault = NULL; + copy->action = NULL; +#ifndef WITH_LEAN +#ifdef WITH_COOKIES + copy->cookies = soap_copy_cookies(copy, soap); +#else + copy->cookies = NULL; +#endif +#endif + copy->plugins = NULL; + for (p = soap->plugins; p; p = p->next) + { register struct soap_plugin *q = (struct soap_plugin*)SOAP_MALLOC(copy, sizeof(struct soap_plugin)); + if (!q) + return NULL; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Copying plugin '%s'\n", p->id)); + *q = *p; + if (p->fcopy && (soap->error = p->fcopy(copy, q, p))) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not copy plugin '%s'\n", p->id)); + SOAP_FREE(copy, q); + return NULL; + } + q->next = copy->plugins; + copy->plugins = q; + } + } + else + soap->error = SOAP_EOM; + return copy; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_copy_stream(struct soap *copy, struct soap *soap) +{ copy->mode = soap->mode; + copy->imode = soap->imode; + copy->omode = soap->omode; + copy->socket = soap->socket; + copy->recv_timeout = soap->recv_timeout; + copy->send_timeout = soap->send_timeout; +#if defined(__cplusplus) && !defined(WITH_LEAN) + copy->os = soap->os; + copy->is = soap->is; +#endif + copy->sendfd = soap->sendfd; + copy->recvfd = soap->recvfd; + copy->bufidx = soap->bufidx; + copy->buflen = soap->buflen; + copy->ahead = soap->ahead; + copy->cdata = soap->cdata; + copy->chunksize = soap->chunksize; + copy->chunkbuflen = soap->chunkbuflen; + copy->keep_alive = soap->keep_alive; + copy->tcp_keep_alive = soap->tcp_keep_alive; + copy->tcp_keep_idle = soap->tcp_keep_idle; + copy->tcp_keep_intvl = soap->tcp_keep_intvl; + copy->tcp_keep_cnt = soap->tcp_keep_cnt; + copy->max_keep_alive = soap->max_keep_alive; +#ifndef WITH_NOIO + copy->peer = soap->peer; + copy->peerlen = soap->peerlen; +#endif +#ifdef WITH_OPENSSL + copy->bio = soap->bio; + copy->ssl = soap->ssl; + copy->ctx = soap->ctx; +#endif +#ifdef WITH_ZLIB + copy->zlib_state = soap->zlib_state; + copy->zlib_in = soap->zlib_in; + copy->zlib_out = soap->zlib_out; + copy->d_stream = soap->d_stream; + copy->z_buflen = soap->z_buflen; + copy->z_level = soap->z_level; + copy->z_crc = soap->z_crc; + copy->z_ratio_in = soap->z_ratio_in; + copy->z_ratio_out = soap->z_ratio_out; + memcpy(copy->z_buf, soap->z_buf, sizeof(soap->z_buf)); +#endif + memcpy(copy->buf, soap->buf, sizeof(soap->buf)); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_init(struct soap *soap) +{ soap->state = SOAP_INIT; + soap->version = 0; + soap_imode(soap, SOAP_IO_DEFAULT); + soap_omode(soap, SOAP_IO_DEFAULT); + soap->plugins = NULL; + soap->user = NULL; + soap->userid = NULL; + soap->passwd = NULL; +#ifndef WITH_NOHTTP + soap->fpost = http_post; + soap->fget = http_get; + soap->fform = NULL; + soap->fposthdr = http_post_header; + soap->fresponse = http_response; + soap->fparse = http_parse; + soap->fparsehdr = http_parse_header; +#endif + soap->fheader = NULL; + soap->fconnect = NULL; + soap->fdisconnect = NULL; +#ifndef WITH_NOIO +#ifndef WITH_IPV6 + soap->fresolve = tcp_gethost; +#else + soap->fresolve = NULL; +#endif + soap->faccept = tcp_accept; + soap->fopen = tcp_connect; + soap->fclose = tcp_disconnect; + soap->fclosesocket = tcp_closesocket; + soap->fshutdownsocket = tcp_shutdownsocket; + soap->fsend = fsend; + soap->frecv = frecv; + soap->fpoll = soap_poll; +#else + soap->fopen = NULL; + soap->fclose = NULL; + soap->fpoll = NULL; +#endif + soap->fseterror = NULL; + soap->fignore = NULL; + soap->fserveloop = NULL; + soap->fplugin = fplugin; + soap->fmalloc = NULL; +#ifndef WITH_LEANER + soap->fprepareinit = NULL; + soap->fpreparesend = NULL; + soap->fpreparerecv = NULL; + soap->fpreparefinal = NULL; + soap->fdimereadopen = NULL; + soap->fdimewriteopen = NULL; + soap->fdimereadclose = NULL; + soap->fdimewriteclose = NULL; + soap->fdimeread = NULL; + soap->fdimewrite = NULL; + soap->fmimereadopen = NULL; + soap->fmimewriteopen = NULL; + soap->fmimereadclose = NULL; + soap->fmimewriteclose = NULL; + soap->fmimeread = NULL; + soap->fmimewrite = NULL; +#endif + soap->float_format = "%.9G"; /* Alternative: use "%G" */ + soap->double_format = "%.17lG"; /* Alternative: use "%lG" */ + soap->dime_id_format = "cid:id%d"; /* default DIME id format */ + soap->http_version = "1.1"; + soap->proxy_http_version = "1.0"; + soap->http_content = NULL; + soap->actor = NULL; + soap->keep_alive = 0; + soap->tcp_keep_alive = 0; + soap->tcp_keep_idle = 0; + soap->tcp_keep_intvl = 0; + soap->tcp_keep_cnt = 0; + soap->max_keep_alive = SOAP_MAXKEEPALIVE; + soap->recv_timeout = 0; + soap->send_timeout = 0; + soap->connect_timeout = 0; + soap->accept_timeout = 0; + soap->socket_flags = 0; + soap->connect_flags = 0; + soap->bind_flags = 0; + soap->accept_flags = 0; + soap->ip = 0; + soap->labbuf = NULL; + soap->lablen = 0; + soap->labidx = 0; + soap->encodingStyle = SOAP_STR_EOS; +#ifndef WITH_NONAMESPACES + soap->namespaces = namespaces; +#else + soap->namespaces = NULL; +#endif + soap->local_namespaces = NULL; + soap->nlist = NULL; + soap->blist = NULL; + soap->clist = NULL; + soap->alist = NULL; + soap->attributes = NULL; + soap->header = NULL; + soap->fault = NULL; + soap->master = SOAP_INVALID_SOCKET; + soap->socket = SOAP_INVALID_SOCKET; + soap->os = NULL; + soap->is = NULL; +#ifndef WITH_LEANER + soap->dom = NULL; + soap->dime.list = NULL; + soap->dime.first = NULL; + soap->dime.last = NULL; + soap->mime.list = NULL; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = NULL; + soap->mime.start = NULL; + soap->xlist = NULL; +#endif +#ifndef UNDER_CE + soap->recvfd = 0; + soap->sendfd = 1; +#else + soap->recvfd = stdin; + soap->sendfd = stdout; +#endif + soap->host[0] = '\0'; + soap->port = 0; + soap->action = NULL; + soap->proxy_host = NULL; + soap->proxy_port = 8080; + soap->proxy_userid = NULL; + soap->proxy_passwd = NULL; + soap->authrealm = NULL; + soap->prolog = NULL; +#ifdef WITH_ZLIB + soap->zlib_state = SOAP_ZLIB_NONE; + soap->zlib_in = SOAP_ZLIB_NONE; + soap->zlib_out = SOAP_ZLIB_NONE; + soap->d_stream.zalloc = NULL; + soap->d_stream.zfree = NULL; + soap->d_stream.opaque = NULL; + soap->z_level = 6; +#endif +#ifndef WITH_LEAN + soap->c14ninclude = NULL; + soap->c14nexclude = NULL; + soap->cookies = NULL; + soap->cookie_domain = NULL; + soap->cookie_path = NULL; + soap->cookie_max = 32; +#endif +#ifdef SOAP_MEM_DEBUG + soap_init_mht(soap); +#endif +#ifdef SOAP_DEBUG + soap_init_logs(soap); +#endif +#ifdef WMW_RPM_IO + soap->rpmreqid = NULL; +#endif +#ifdef PALM + palmNetLibOpen(); +#endif +#ifndef WITH_NOIDREF + soap_init_iht(soap); + soap_init_pht(soap); +#endif +#ifdef SOAP_DEBUG + soap_set_recv_logfile(soap, "RECV.log"); + soap_set_sent_logfile(soap, "SENT.log"); + soap_set_test_logfile(soap, "TEST.log"); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing context\n")); +#endif +#ifdef WITH_OPENSSL + if (!ssl_init_done) + { soap_ssl_init(); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing OpenSSL, version=%ld\n", (long)OPENSSL_VERSION_NUMBER)); + } + soap->fsslauth = ssl_auth_init; + soap->fsslverify = ssl_verify_callback; + soap->bio = NULL; + soap->ssl = NULL; + soap->ctx = NULL; + soap->ssl_flags = SOAP_SSL_DEFAULT; + soap->keyfile = NULL; + soap->password = NULL; + soap->dhfile = NULL; + soap->cafile = NULL; + soap->capath = NULL; + soap->crlfile = NULL; + soap->randfile = NULL; + soap->session = NULL; +#endif + soap_begin(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_init1(struct soap *soap, soap_mode mode) +{ soap_init2(soap, mode, mode); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_init2(struct soap *soap, soap_mode imode, soap_mode omode) +{ soap_init(soap); + soap_imode(soap, imode); + soap_omode(soap, omode); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_begin(struct soap *soap) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reinitializing context\n")); + if (!soap->keep_alive) + { soap->buflen = 0; + soap->bufidx = 0; + } + soap->keep_alive = (((soap->imode | soap->omode) & SOAP_IO_KEEPALIVE) != 0); + soap->null = 0; + soap->position = 0; + soap->encoding = 0; + soap->mustUnderstand = 0; + soap->mode = 0; + soap->ns = 0; + soap->part = SOAP_END; + soap->alloced = 0; + soap->count = 0; + soap->length = 0; + soap->cdata = 0; + soap->error = SOAP_OK; + soap->peeked = 0; + soap->ahead = 0; + soap->idnum = 0; + soap->level = 0; + soap->endpoint[0] = '\0'; +#ifndef WITH_LEANER + soap->dime.chunksize = 0; + soap->dime.buflen = 0; +#endif + soap_free_temp(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_end(struct soap *soap) +{ if (soap_check_state(soap)) + return; + soap_free_temp(soap); + soap_dealloc(soap, NULL); + while (soap->clist) + { register struct soap_clist *cp = soap->clist->next; + SOAP_FREE(soap, soap->clist); + soap->clist = cp; + } + soap_closesock(soap); +#ifdef SOAP_DEBUG + soap_close_logfiles(soap); +#endif +#ifdef PALM + palmNetLibClose(); +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_namespaces(struct soap *soap, const struct Namespace *p) +{ register struct Namespace *ns = soap->local_namespaces; + register struct soap_nlist *np, *nq, *nr; + register unsigned int level = soap->level; + soap->namespaces = p; + soap->local_namespaces = NULL; + soap_set_local_namespaces(soap); + /* reverse the namespace list */ + np = soap->nlist; + soap->nlist = NULL; + if (np) + { nq = np->next; + np->next = NULL; + while (nq) + { nr = nq->next; + nq->next = np; + np = nq; + nq = nr; + } + } + /* then push on new stack */ + while (np) + { register const char *s; + soap->level = np->level; /* preserve element nesting level */ + s = np->ns; + if (!s && np->index >= 0 && ns) + { s = ns[np->index].out; + if (!s) + s = ns[np->index].ns; + } + if (s && soap_push_namespace(soap, np->id, s)) + return soap->error; + nq = np; + np = np->next; + SOAP_FREE(soap, nq); + } + if (ns) + { register int i; + for (i = 0; ns[i].id; i++) + { if (ns[i].out) + { SOAP_FREE(soap, ns[i].out); + ns[i].out = NULL; + } + } + SOAP_FREE(soap, ns); + } + soap->level = level; /* restore level */ + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_local_namespaces(struct soap *soap) +{ if (soap->namespaces && !soap->local_namespaces) + { register const struct Namespace *ns1; + register struct Namespace *ns2; + register size_t n = 1; + for (ns1 = soap->namespaces; ns1->id; ns1++) + n++; + n *= sizeof(struct Namespace); + ns2 = (struct Namespace*)SOAP_MALLOC(soap, n); + if (ns2) + { memcpy(ns2, soap->namespaces, n); + if (ns2[0].ns) + { if (!strcmp(ns2[0].ns, soap_env1)) + soap->version = 1; + else + soap->version = 2; + } + soap->local_namespaces = ns2; + } + } +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +#ifndef PALM_1 +SOAP_FMAC1 +const char * +SOAP_FMAC2 +soap_strsearch(const char *big, const char *little) +{ size_t n = strlen(little); + const char *s = big; + while (s) + { if (!strncmp(s, little, n) && (s[n] == '\0' || s[n] == ' ')) + return s; + s = strchr(s, ' '); + if (s) + s++; + } + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +#ifndef PALM_1 +SOAP_FMAC1 +struct soap_nlist * +SOAP_FMAC2 +soap_lookup_ns(struct soap *soap, const char *tag, size_t n) +{ register struct soap_nlist *np; + for (np = soap->nlist; np; np = np->next) + { if (!strncmp(np->id, tag, n) && !np->id[n]) + return np; + } + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static struct soap_nlist * +soap_push_ns(struct soap *soap, const char *id, const char *ns, short utilized) +{ register struct soap_nlist *np; + size_t n, k; + if (soap_strsearch(soap->c14nexclude, id)) + return NULL; + if (!utilized) + { for (np = soap->nlist; np; np = np->next) + { if (!strcmp(np->id, id) && (!np->ns || !strcmp(np->ns, ns))) + break; + } + if (np) + { if ((np->level < soap->level || !np->ns) && np->index == 1) + utilized = 1; + else + return NULL; + } + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Adding namespace binding (level=%u) '%s' '%s' utilized=%d\n", soap->level, id, ns?ns:"(null)", utilized)); + n = strlen(id); + if (ns) + k = strlen(ns); + else + k = 0; + np = (struct soap_nlist*)SOAP_MALLOC(soap, sizeof(struct soap_nlist) + n + k + 1); + if (!np) + { soap->error = SOAP_EOM; + return NULL; + } + np->next = soap->nlist; + soap->nlist = np; + strcpy(np->id, id); + if (ns) + { np->ns = np->id + n + 1; + strcpy(np->ns, ns); + } + else + np->ns = NULL; + np->level = soap->level; + np->index = utilized; + return np; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static void +soap_utilize_ns(struct soap *soap, const char *tag, size_t n) +{ register struct soap_nlist *np = soap_lookup_ns(soap, tag, n); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Utilizing namespace of '%s'\n", tag)); + if (np) + { if (np->index == 0) + soap_push_ns(soap, np->id, np->ns, 1); + } + else if (strncmp(tag, "xml", 3)) + { strncpy(soap->tmpbuf, tag, n); + soap->tmpbuf[n] = '\0'; + soap_push_ns(soap, soap->tmpbuf, NULL, 1); + } +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static void +soap_pop_ns(struct soap *soap) +{ soap_pop_namespace(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element(struct soap *soap, const char *tag, int id, const char *type) +{ +#ifdef WITH_XMLNS + register const char *s; +#endif + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element begin tag='%s' id='%d' type='%s'\n", tag, id, type?type:"")); +#ifdef WITH_DOM + if (soap->part == SOAP_BEGIN_SECURITY && (soap->mode & SOAP_XML_CANONICAL) && !(soap->mode & SOAP_DOM_ASIS)) + { register struct soap_nlist *np; + /* wsu:Id found: clear xmlns renderings, so re-emit them for exc-c14n */ + for (np = soap->nlist; np; np = np->next) + { if (np->index == 2) + np->index = 0; + } + } + if (soap->mode & SOAP_XML_DOM) + { register struct soap_dom_element *elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element)); + if (!elt) + return soap->error = SOAP_EOM; + elt->soap = soap; + elt->next = NULL; + elt->prnt = soap->dom; + elt->name = soap_strdup(soap, tag); + elt->elts = NULL; + elt->atts = NULL; + elt->nstr = NULL; + elt->data = NULL; + elt->wide = NULL; + elt->node = NULL; + elt->type = 0; + elt->head = NULL; + elt->tail = NULL; + if (soap->dom) + { struct soap_dom_element *p = soap->dom->elts; + if (p) + { while (p->next) + p = p->next; + p->next = elt; + } + else + soap->dom->elts = elt; + } + soap->dom = elt; + } + else + { +#endif + soap->level++; +#ifndef WITH_LEAN + if (!soap->ns) + { if (!(soap->mode & SOAP_XML_CANONICAL) + && soap_send(soap, soap->prolog ? soap->prolog : "\n")) + return soap->error; + } + else if (soap->mode & SOAP_XML_INDENT) + { if (soap->ns == 1 && soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1)) + return soap->error; + soap->body = 1; + } +#endif +#ifdef WITH_XMLNS + s = strchr(tag, ':'); + if (s && strncmp(tag, "SOAP-ENV", s - tag)) + { struct Namespace *ns = soap->local_namespaces; + size_t n = s - tag; + if (soap_send_raw(soap, "<", 1) + || soap_send(soap, s + 1)) + return soap->error; + if (soap->nlist && !strncmp(soap->nlist->id, tag, n) && !soap->nlist->id[n]) + ns = NULL; + for (; ns && ns->id; ns++) + { if (*ns->id && (ns->out || ns->ns) && !strncmp(ns->id, tag, n) && !ns->id[n]) + { soap_push_ns(soap, ns->id, ns->out ? ns->out : ns->ns, 0); + if (soap_attribute(soap, "xmlns", ns->out ? ns->out : ns->ns)) + return soap->error; + break; + } + } + } + else +#endif + if (soap_send_raw(soap, "<", 1) + || soap_send(soap, tag)) + return soap->error; +#ifdef WITH_DOM + } +#endif + if (!soap->ns) + { struct Namespace *ns; + for (ns = soap->local_namespaces; ns && ns->id; ns++) + { if (*ns->id && (ns->out || ns->ns)) + { sprintf(soap->tmpbuf, "xmlns:%s", ns->id); + if (soap_attribute(soap, soap->tmpbuf, ns->out ? ns->out : ns->ns)) + return soap->error; + } + } + } + soap->ns = 1; /* start with 0 or 2, but should be one to continue */ +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { const char *t = strchr(tag, ':'); + if (t) + soap_utilize_ns(soap, tag, t - tag); + } +#endif + if (id > 0) + { sprintf(soap->tmpbuf, "_%d", id); + if (soap_attribute(soap, "id", soap->tmpbuf)) + return soap->error; + } + if (type && *type && (!(soap->mode & SOAP_XML_SEC) || soap->part == SOAP_IN_BODY)) + { if (soap_attribute(soap, "xsi:type", type)) + return soap->error; +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { const char *t = strchr(type, ':'); + if (t) + soap_utilize_ns(soap, type, t - type); + } +#endif + } + if (soap->null && soap->position > 0) + { register int i; + sprintf(soap->tmpbuf, "[%d", soap->positions[0]); + for (i = 1; i < soap->position; i++) + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), ",%d", soap->positions[i]); + strcat(soap->tmpbuf, "]"); + if (soap_attribute(soap, "SOAP-ENC:position", soap->tmpbuf)) + return soap->error; + } + if (soap->mustUnderstand) + { if (soap->actor && *soap->actor) + { if (soap_attribute(soap, soap->version == 2 ? "SOAP-ENV:role" : "SOAP-ENV:actor", soap->actor)) + return soap->error; + } + if (soap_attribute(soap, "SOAP-ENV:mustUnderstand", soap->version == 2 ? "true" : "1")) + return soap->error; + soap->mustUnderstand = 0; + } + if (soap->encoding) + { if (soap->encodingStyle && soap->local_namespaces) + { if (!*soap->encodingStyle) + { if (soap->local_namespaces[1].out) + soap->encodingStyle = soap->local_namespaces[1].out; + else + soap->encodingStyle = soap->local_namespaces[1].ns; + } + if (soap_attribute(soap, "SOAP-ENV:encodingStyle", soap->encodingStyle)) + return soap->error; + } + soap->encoding = 0; + } + soap->null = 0; + soap->position = 0; + if (soap->part == SOAP_BEGIN_SECURITY && (soap->mode & SOAP_XML_CANONICAL)) + soap->part = SOAP_IN_SECURITY; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_begin_out(struct soap *soap, const char *tag, int id, const char *type) +{ if (*tag == '-') + return SOAP_OK; + if (soap_element(soap, tag, id, type)) + return soap->error; + return soap_element_start_end_out(soap, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +#ifndef HAVE_STRRCHR +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_strrchr(const char *s, int t) +{ register char *r = NULL; + while (*s) + if (*s++ == t) + r = (char*)s - 1; + return r; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +#ifndef HAVE_STRTOL +SOAP_FMAC1 +long +SOAP_FMAC2 +soap_strtol(const char *s, char **t, int b) +{ register long n = 0; + register int c; + while (*s > 0 && *s <= 32) + s++; + if (b == 10) + { short neg = 0; + if (*s == '-') + { s++; + neg = 1; + } + else if (*s == '+') + s++; + while ((c = *s) && c >= '0' && c <= '9') + { if (n >= 214748364 && (n > 214748364 || c >= '8')) + break; + n *= 10; + n += c - '0'; + s++; + } + if (neg) + n = -n; + } + else /* b == 16 and value is always positive */ + { while ((c = *s)) + { if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'F') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'f') + c -= 'a' - 10; + if (n > 0x07FFFFFF) + break; + n <<= 4; + n += c; + s++; + } + } + if (t) + *t = (char*)s; + return n; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +#ifndef HAVE_STRTOUL +SOAP_FMAC1 +unsigned long +SOAP_FMAC2 +soap_strtoul(const char *s, char **t, int b) +{ unsigned long n = 0; + register int c; + while (*s > 0 && *s <= 32) + s++; + if (b == 10) + { if (*s == '+') + s++; + while ((c = *s) && c >= '0' && c <= '9') + { if (n >= 429496729 && (n > 429496729 || c >= '6')) + break; + n *= 10; + n += c - '0'; + s++; + } + } + else /* b == 16 */ + { while ((c = *s)) + { if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'F') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'f') + c -= 'a' - 10; + if (n > 0x0FFFFFFF) + break; + n <<= 4; + n += c; + s++; + } + } + if (t) + *t = (char*)s; + return n; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_array_begin_out(struct soap *soap, const char *tag, int id, const char *type, const char *offset) +{ if (soap_element(soap, tag, id, "SOAP-ENC:Array")) + return soap->error; + if (soap->version == 2) + { const char *s; + s = soap_strrchr(type, '['); + if ((size_t)(s - type) < sizeof(soap->tmpbuf)) + { strncpy(soap->tmpbuf, type, s - type); + soap->tmpbuf[s - type] = '\0'; + if (type && *type && (soap_attribute(soap, "SOAP-ENC:itemType", soap->tmpbuf))) + return soap->error; + if (s && (soap_attribute(soap, "SOAP-ENC:arraySize", s + 1))) + return soap->error; + } + } + else + { if (offset && (soap_attribute(soap, "SOAP-ENC:offset", offset))) + return soap->error; + if (type && *type && (soap_attribute(soap, "SOAP-ENC:arrayType", type))) + return soap->error; + } +#ifndef WITH_LEAN + if (type && *type && (soap->mode & SOAP_XML_CANONICAL)) + { const char *s = strchr(type, ':'); + if (s) + soap_utilize_ns(soap, type, s - type); + } +#endif + return soap_element_start_end_out(soap, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_start_end_out(struct soap *soap, const char *tag) +{ register struct soap_attribute *tp; +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { struct soap_nlist *np; + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible && tp->name) + { const char *s = strchr(tp->name, ':'); + if (s) + soap_utilize_ns(soap, tp->name, s - tp->name); + } + } + for (np = soap->nlist; np; np = np->next) + { if (np->index == 1 && np->ns) + { sprintf(soap->tmpbuf, "xmlns:%s", np->id); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enabling utilized binding (level=%u) %s='%s'\n", np->level, soap->tmpbuf, np->ns)); + soap_set_attr(soap, soap->tmpbuf, np->ns); + np->index = 2; + } + } + } +#endif +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { register struct soap_dom_attribute **att; + att = &soap->dom->atts; + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible) + { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); + if (!*att) + return soap->error = SOAP_EOM; + (*att)->next = NULL; + (*att)->nstr = NULL; + (*att)->name = soap_strdup(soap, tp->name); + (*att)->data = soap_strdup(soap, tp->value); + (*att)->wide = NULL; + (*att)->soap = soap; + att = &(*att)->next; + tp->visible = 0; + } + } + return SOAP_OK; + } +#endif + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible) + { +#ifdef WITH_XMLNS + const char *s = strchr(tp->name, ':'); + if (s) + { size_t n = s - tp->name; + if (soap->nlist && !strncmp(soap->nlist->id, tp->name, n) && !soap->nlist->id[n]) + s++; + else + s = tp->name; + if (soap_send(soap, " ") || soap_send(soap, s)) + return soap->error; + } + else +#endif + if (soap_send(soap, " ") || soap_send(soap, tp->name)) + return soap->error; + if (tp->visible == 2 && tp->value) + if (soap_send_raw(soap, "=\"", 2) + || soap_string_out(soap, tp->value, 1) + || soap_send_raw(soap, "\"", 1)) + return soap->error; + tp->visible = 0; + } + } + if (tag) + { +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { if (soap_send_raw(soap, ">", 1) + || soap_element_end_out(soap, tag)) + return soap->error; + return SOAP_OK; + } +#endif + soap->level--; /* decrement level just before /> */ + if (soap_send_raw(soap, "/>", 2)) + return soap->error; + return SOAP_OK; + } + return soap_send_raw(soap, ">", 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_end_out(struct soap *soap, const char *tag) +{ if (*tag == '-') + return SOAP_OK; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element ending tag='%s'\n", tag)); +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { if (soap->dom->prnt) + soap->dom = soap->dom->prnt; + return SOAP_OK; + } +#endif +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + soap_pop_ns(soap); + if (soap->mode & SOAP_XML_INDENT) + { if (!soap->body) + { if (soap_send_raw(soap, soap_indent, soap->level < sizeof(soap_indent) ? soap->level : sizeof(soap_indent) - 1)) + return soap->error; + } + soap->body = 0; + } +#endif +#ifdef WITH_XMLNS + { const char *s = strchr(tag, ':'); + if (s && strncmp(tag, "SOAP-ENV", s - tag)) + { soap_pop_ns(soap); + tag = s + 1; + } + } +#endif + if (soap_send_raw(soap, "error; + soap->level--; /* decrement level just before > */ + return soap_send_raw(soap, ">", 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_ref(struct soap *soap, const char *tag, int id, int href) +{ register int n = 0; + const char *s = "href"; + if (soap->version == 2) + { s = "SOAP-ENC:ref"; + n = 1; + } + sprintf(soap->href, "#_%d", href); + return soap_element_href(soap, tag, id, s, soap->href + n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_href(struct soap *soap, const char *tag, int id, const char *ref, const char *val) +{ DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element '%s' reference %s='%s'\n", tag, ref, val)); + if (soap_element(soap, tag, id, NULL) + || soap_attribute(soap, ref, val) + || soap_element_start_end_out(soap, tag)) + return soap->error; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_null(struct soap *soap, const char *tag, int id, const char *type) +{ struct soap_attribute *tp; + for (tp = soap->attributes; tp; tp = tp->next) + if (tp->visible) + break; + if (tp || (soap->version == 2 && soap->position > 0) || id > 0 || (soap->mode & SOAP_XML_NIL)) + { if (soap_element(soap, tag, id, type)) + return soap->error; + if (soap->part != SOAP_IN_HEADER && soap->encodingStyle) + if (soap_attribute(soap, "xsi:nil", "true")) + return soap->error; + return soap_element_start_end_out(soap, tag); + } + soap->null = 1; + soap->position = 0; + soap->mustUnderstand = 0; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_id(struct soap *soap, const char *tag, int id, const void *p, const struct soap_array *a, int n, const char *type, int t) +{ if (!p || (a && !a->__ptr)) + { soap_element_null(soap, tag, id, type); + return -1; + } +#ifndef WITH_NOIDREF + if (soap->mode & SOAP_XML_TREE) + return 0; + if (id < 0) + { struct soap_plist *pp; + if (a) + id = soap_array_pointer_lookup(soap, p, a, n, t, &pp); + else + id = soap_pointer_lookup(soap, p, t, &pp); + if (id) + { if (soap_is_embedded(soap, pp)) + { soap_element_ref(soap, tag, 0, id); + return -1; + } + if (soap_is_single(soap, pp)) + return 0; + soap_set_embedded(soap, pp); + } + } + return id; +#else + return 0; +#endif +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_result(struct soap *soap, const char *tag) +{ if (soap->version == 2 && soap->encodingStyle) + { if (soap_element(soap, "SOAP-RPC:result", 0, NULL) + || soap_attribute(soap, "xmlns:SOAP-RPC", soap_rpc) + || soap_element_start_end_out(soap, NULL) + || soap_string_out(soap, tag, 0) + || soap_element_end_out(soap, "SOAP-RPC:result")) + return soap->error; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_check_result(struct soap *soap, const char *tag) +{ if (soap->version == 2 && soap->encodingStyle) + { soap_instring(soap, ":result", NULL, NULL, 0, 2, -1, -1); + /* just ignore content for compliance reasons, but should compare tag to element's QName value? */ + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_attribute(struct soap *soap, const char *name, const char *value) +{ +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && !(soap->mode & SOAP_XML_CANONICAL) && soap->dom) + { register struct soap_dom_attribute *a = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); + a->next = soap->dom->atts; + a->nstr = NULL; + a->name = soap_strdup(soap, name); + a->data = soap_strdup(soap, value); + a->wide = NULL; + a->soap = soap; + soap->dom->atts = a; + return SOAP_OK; + } +#endif +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { /* TODO: consider using this code to handle default namespace bindings + if (!strncmp(name, "xmlns", 5) && (name[5] == ':' || name[5] == '\0')) + { if (name[5] == ':') + soap_push_ns(soap, name + 6, value, 0); + else + soap_push_ns(soap, "", value, 0); + } + */ + if (!strncmp(name, "xmlns:", 6)) + soap_push_ns(soap, name + 6, value, 0); + else if (soap_set_attr(soap, name, value)) + return soap->error; + } + else +#endif + { if (soap_send(soap, " ") || soap_send(soap, name)) + return soap->error; + if (value) + if (soap_send_raw(soap, "=\"", 2) + || soap_string_out(soap, value, 1) + || soap_send_raw(soap, "\"", 1)) + return soap->error; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_begin_in(struct soap *soap, const char *tag, int nillable, const char *type) +{ if (!soap_peek_element(soap)) + { if (soap->other) + return soap->error = SOAP_TAG_MISMATCH; + if (tag && *tag == '-') + return SOAP_OK; + if (!(soap->error = soap_match_tag(soap, soap->tag, tag))) + { soap->peeked = 0; + if (type && *soap->type && soap_match_tag(soap, soap->type, type)) + return soap->error = SOAP_TYPE; + if (!nillable && soap->null && (soap->mode & SOAP_XML_STRICT)) + return soap->error = SOAP_NULL; + if (soap->body) + soap->level++; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Begin element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:"" )); + } + } + else if (soap->error == SOAP_NO_TAG && tag && *tag == '-') + soap->error = SOAP_OK; + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_element_end_in(struct soap *soap, const char *tag) +{ register soap_wchar c; + register char *s; + register int n = 0; + if (tag && *tag == '-') + return SOAP_OK; + if (soap->error == SOAP_NO_TAG) + soap->error = SOAP_OK; +#ifdef WITH_DOM + /* this whitespace or mixed content is not insignificant for DOM */ + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { if (!soap->peeked && !soap_string_in(soap, 3, -1, -1)) + return soap->error; + if (soap->dom->prnt) + soap->dom = soap->dom->prnt; + } +#endif + if (soap->peeked) + { if (*soap->tag) + n++; + soap->peeked = 0; + } + do + { while (((c = soap_get(soap)) != SOAP_TT)) + { if ((int)c == EOF) + return soap->error = SOAP_EOF; + if (c == SOAP_LT) + n++; + else if (c == '/') + { c = soap_get(soap); + if (c == SOAP_GT) + n--; + else + soap_unget(soap, c); + } + } + } while (n--); + s = soap->tag; + n = sizeof(soap->tag); + while (soap_notblank(c = soap_get(soap))) + { if (--n > 0) + *s++ = (char)c; + } + *s = '\0'; + if ((int)c == EOF) + return soap->error = SOAP_EOF; + while (soap_blank(c)) + c = soap_get(soap); + if (c != SOAP_GT) + return soap->error = SOAP_SYNTAX_ERROR; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element found (level=%u) '%s'='%s'\n", soap->level, soap->tag, tag?tag:"")); +#ifndef WITH_LEAN + if (tag && (soap->mode & SOAP_XML_STRICT)) + { soap_pop_namespace(soap); + if (soap_match_tag(soap, soap->tag, tag)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "End element tag name does not match\n")); + return soap->error = SOAP_SYNTAX_ERROR; + } + } +#endif + soap->level--; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char * +SOAP_FMAC2 +soap_attr_value(struct soap *soap, const char *name, int flag) +{ register struct soap_attribute *tp; + if (*name == '-') + return SOAP_STR_EOS; + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible && !soap_match_tag(soap, tp->name, name)) + break; + } + if (tp) + { if (flag == 2 && (soap->mode & SOAP_XML_STRICT)) + soap->error = SOAP_PROHIBITED; + else + return tp->value; + } + else if (flag == 1 && (soap->mode & SOAP_XML_STRICT)) + soap->error = SOAP_REQUIRED; + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_attr(struct soap *soap, const char *name, const char *value) +{ register struct soap_attribute *tp; + if (*name == '-') + return SOAP_OK; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set attribute %s='%s'\n", name, value?value:"")); + for (tp = soap->attributes; tp; tp = tp->next) + { if (!strcmp(tp->name, name)) + break; + } + if (!tp) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute %s\n", name)); + if (!(tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(name)))) + return soap->error = SOAP_EOM; + tp->ns = NULL; +#ifndef WITH_LEAN + if (soap->mode & SOAP_XML_CANONICAL) + { struct soap_attribute **tpp = &soap->attributes; + const char *s = strchr(name, ':'); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inserting attribute %s for c14n\n", name)) + if (!strncmp(name, "xmlns", 5)) + { for (; *tpp; tpp = &(*tpp)->next) + if (strncmp((*tpp)->name, "xmlns", 5) || strcmp((*tpp)->name + 5, name + 5) > 0) + break; + } + else if (!s) + { for (; *tpp; tpp = &(*tpp)->next) + if (strncmp((*tpp)->name, "xmlns", 5) && ((*tpp)->ns || strcmp((*tpp)->name, name) > 0)) + break; + } + else + { int k; + for (; *tpp; tpp = &(*tpp)->next) + { if (!strncmp((*tpp)->name, "xmlns:", 6) && !strncmp((*tpp)->name + 6, name, s - name) && !(*tpp)->name[6 + s - name]) + { if (!tp->ns) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Canonicalization: prefix %s=%p (%s)\n", name, (*tpp)->ns, (*tpp)->ns)); + tp->ns = (*tpp)->ns; + } + } + else if (strncmp((*tpp)->name, "xmlns", 5) && (*tpp)->ns && tp->ns && ((k = strcmp((*tpp)->ns, tp->ns)) > 0 || (!k && strcmp((*tpp)->name, name) > 0))) + break; + } + } + tp->next = *tpp; + *tpp = tp; + } + else +#endif + { tp->next = soap->attributes; + soap->attributes = tp; + } + strcpy(tp->name, name); + tp->value = NULL; + } + else if (tp->visible) + { return SOAP_OK; + } + else if (value && tp->value && tp->size <= strlen(value)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Free attribute value of %s (free %p)\n", name, tp->value)); + SOAP_FREE(soap, tp->value); + tp->value = NULL; + tp->ns = NULL; + } + if (value) + { if (!tp->value) + { tp->size = strlen(value) + 1; + if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size))) + return soap->error = SOAP_EOM; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Allocate attribute value for %s (%p)\n", tp->name, tp->value)); + } + strcpy(tp->value, value); + if (!strncmp(tp->name, "xmlns:", 6)) + tp->ns = tp->value; + tp->visible = 2; +#ifndef WITH_LEAN + if (!strcmp(name, "wsu:Id")) + { soap->part = SOAP_BEGIN_SECURITY; + strncpy(soap->id, value, sizeof(soap->id)); + soap->id[sizeof(soap->id)-1] = '\0'; + } +#endif + } + else + tp->visible = 1; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_clr_attr(struct soap *soap) +{ register struct soap_attribute *tp; +#ifndef WITH_LEAN + if ((soap->mode & SOAP_XML_CANONICAL)) + { while (soap->attributes) + { tp = soap->attributes->next; + if (soap->attributes->value) + SOAP_FREE(soap, soap->attributes->value); + SOAP_FREE(soap, soap->attributes); + soap->attributes = tp; + } + } + else +#endif + { for (tp = soap->attributes; tp; tp = tp->next) + tp->visible = 0; + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +static int +soap_getattrval(struct soap *soap, char *s, size_t n, soap_wchar d) +{ register size_t i; + for (i = 0; i < n; i++) + { register soap_wchar c = soap_get(soap); + switch (c) + { + case SOAP_TT: + *s++ = '<'; + soap_unget(soap, '/'); + break; + case SOAP_LT: + *s++ = '<'; + break; + case SOAP_GT: + if (d == ' ') + { soap_unget(soap, c); + *s = '\0'; + return SOAP_OK; + } + *s++ = '>'; + break; + case SOAP_QT: + if (c == d) + { *s = '\0'; + return SOAP_OK; + } + *s++ = '"'; + break; + case SOAP_AP: + if (c == d) + { *s = '\0'; + return SOAP_OK; + } + *s++ = '\''; + break; + case '\t': + case '\n': + case '\r': + case ' ': + case '/': + if (d == ' ') + { soap_unget(soap, c); + *s = '\0'; + return SOAP_OK; + } + default: + if ((int)c == EOF) + return soap->error = SOAP_EOF; + *s++ = (char)c; + } + } + return soap->error = SOAP_EOM; +} +#endif + +/******************************************************************************/ +#ifdef WITH_FAST +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_store_lab(struct soap *soap, const char *s, size_t n) +{ soap->labidx = 0; + return soap_append_lab(soap, s, n); +} +#endif +#endif + +/******************************************************************************/ +#ifdef WITH_FAST +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_append_lab(struct soap *soap, const char *s, size_t n) +{ if (soap->labidx + n >= soap->lablen) + { register char *t = soap->labbuf; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Enlarging look-aside buffer to append data, old size=%lu", (unsigned long)soap->lablen)); + if (soap->lablen == 0) + soap->lablen = SOAP_LABLEN; + while (soap->labidx + n >= soap->lablen) + soap->lablen <<= 1; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, ", new size=%lu\n", (unsigned long)soap->lablen)); + soap->labbuf = (char*)SOAP_MALLOC(soap, soap->lablen); + if (!soap->labbuf) + { if (t) + SOAP_FREE(soap, t); + return soap->error = SOAP_EOM; + } + if (t) + { memcpy(soap->labbuf, t, soap->labidx); + SOAP_FREE(soap, t); + } + } + if (s) + { memcpy(soap->labbuf + soap->labidx, s, n); + soap->labidx += n; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_peek_element(struct soap *soap) +{ +#ifdef WITH_DOM + register struct soap_dom_attribute **att = NULL; + register char *lead = NULL; +#endif + register struct soap_attribute *tp, *tq = NULL; + const char *t; + register char *s; + register soap_wchar c; + register int i; + if (soap->peeked) + { if (!*soap->tag) + return soap->error = SOAP_NO_TAG; + return SOAP_OK; + } + soap->peeked = 1; + soap->id[0] = '\0'; + soap->href[0] = '\0'; + soap->type[0] = '\0'; + soap->arrayType[0] = '\0'; + soap->arraySize[0] = '\0'; + soap->arrayOffset[0] = '\0'; + soap->other = 0; + soap->root = -1; + soap->position = 0; + soap->null = 0; + soap->mustUnderstand = 0; + c = soap_getutf8(soap); +#ifdef WITH_DOM + /* whitespace leading to start tag is not insignificant for DOM */ + if (soap_blank(c)) + { soap->labidx = 0; + do + { if (soap_append_lab(soap, NULL, 0)) + return SOAP_EOM; + s = soap->labbuf + soap->labidx; + i = soap->lablen - soap->labidx; + soap->labidx = soap->lablen; + while (soap_blank(c) && i--) + { *s++ = c; + c = soap_getutf8(soap); + } + } + while (soap_blank(c)); + *s = '\0'; + lead = soap_strdup(soap, soap->labbuf); + } +#else + while (soap_blank(c)) + c = soap_getutf8(soap); +#endif + if (c != SOAP_LT) + { *soap->tag = '\0'; + if ((int)c == EOF) + return soap->error = SOAP_EOF; + soap_unget(soap, c); +#ifdef WITH_DOM + /* whitespace leading to end tag is not insignificant for DOM */ + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + soap->dom->tail = soap_strdup(soap, lead); +#endif + return soap->error = SOAP_NO_TAG; + } + s = soap->tag; + do c = soap_get1(soap); + while (soap_blank(c)); + i = sizeof(soap->tag); + while (c != '>' && c != '/' && soap_notblank(c) && (int)c != EOF) + { if (--i > 0) + *s++ = (char)c; + c = soap_get1(soap); + } + while (soap_blank(c)) + c = soap_get1(soap); + *s = '\0'; +#ifdef WITH_DOM + if (soap->mode & SOAP_XML_DOM) + { register struct soap_dom_element *elt; + elt = (struct soap_dom_element*)soap_malloc(soap, sizeof(struct soap_dom_element)); + if (!elt) + return soap->error = SOAP_EOM; + elt->next = NULL; + elt->nstr = NULL; + elt->name = soap_strdup(soap, soap->tag); + elt->prnt = soap->dom; + elt->elts = NULL; + elt->atts = NULL; + elt->data = NULL; + elt->wide = NULL; + elt->type = 0; + elt->node = NULL; + elt->head = lead; + elt->tail = NULL; + elt->soap = soap; + if (soap->dom) + { struct soap_dom_element *p = soap->dom->elts; + if (p) + { while (p->next) + p = p->next; + p->next = elt; + } + else + soap->dom->elts = elt; + } + soap->dom = elt; + att = &elt->atts; + } +#endif + soap_pop_namespace(soap); + for (tp = soap->attributes; tp; tp = tp->next) + tp->visible = 0; + while ((int)c != EOF && c != '>' && c != '/') + { s = soap->tmpbuf; + i = sizeof(soap->tmpbuf); + while (c != '=' && c != '>' && c != '/' && soap_notblank(c) && (int)c != EOF) + { if (--i > 0) + *s++ = (char)c; + c = soap_get1(soap); + } + *s = '\0'; + if (i == sizeof(soap->tmpbuf)) + return soap->error = SOAP_SYNTAX_ERROR; +#ifdef WITH_DOM + /* add attribute name to dom */ + if (att) + { *att = (struct soap_dom_attribute*)soap_malloc(soap, sizeof(struct soap_dom_attribute)); + if (!*att) + return soap->error = SOAP_EOM; + (*att)->next = NULL; + (*att)->nstr = NULL; + (*att)->name = soap_strdup(soap, soap->tmpbuf); + (*att)->data = NULL; + (*att)->wide = NULL; + (*att)->soap = soap; + } +#endif + if (!strncmp(soap->tmpbuf, "xmlns", 5)) + { if (soap->tmpbuf[5] == ':') + t = soap->tmpbuf + 6; + else if (soap->tmpbuf[5]) + t = NULL; + else + t = SOAP_STR_EOS; + } + else + t = NULL; + tq = NULL; + for (tp = soap->attributes; tp; tq = tp, tp = tp->next) + { if (!SOAP_STRCMP(tp->name, soap->tmpbuf)) + break; + } + if (!tp) + { tp = (struct soap_attribute*)SOAP_MALLOC(soap, sizeof(struct soap_attribute) + strlen(soap->tmpbuf)); + if (!tp) + return soap->error = SOAP_EOM; + strcpy(tp->name, soap->tmpbuf); + tp->value = NULL; + tp->size = 0; + /* if attribute name is qualified, append it to the end of the list */ + if (tq && strchr(soap->tmpbuf, ':')) + { tq->next = tp; + tp->next = NULL; + } + else + { tp->next = soap->attributes; + soap->attributes = tp; + } + } + while (soap_blank(c)) + c = soap_get1(soap); + if (c == '=') + { do c = soap_getutf8(soap); + while (soap_blank(c)); + if (c != SOAP_QT && c != SOAP_AP) + { soap_unget(soap, c); + c = ' '; /* blank delimiter */ + } + if (soap_getattrval(soap, tp->value, tp->size, c)) + { +#ifdef WITH_FAST + if (soap->error != SOAP_EOM) + return soap->error; + soap->error = SOAP_OK; + if (soap_store_lab(soap, tp->value, tp->size)) + return soap->error; + if (tp->value) + SOAP_FREE(soap, tp->value); + for (;;) + { if (soap_getattrval(soap, soap->labbuf + soap->labidx, soap->lablen - soap->labidx, c)) + { if (soap->error != SOAP_EOM) + return soap->error; + soap->error = SOAP_OK; + soap->labidx = soap->lablen; + if (soap_append_lab(soap, NULL, 0)) + return soap->error; + } + else + break; + } + if (soap->labidx) + tp->size = soap->lablen; + else + { tp->size = strlen(soap->labbuf) + 1; + if (tp->size < SOAP_LABLEN) + tp->size = SOAP_LABLEN; + } + if (!(tp->value = (char*)SOAP_MALLOC(soap, tp->size))) + return soap->error = SOAP_EOM; + strcpy(tp->value, soap->labbuf); +#else + size_t n; + if (soap->error != SOAP_EOM) + return soap->error; + soap->error = SOAP_OK; + if (soap_new_block(soap)) + return soap->error; + for (;;) + { if (!(s = (char*)soap_push_block(soap, SOAP_BLKLEN))) + return soap->error; + if (soap_getattrval(soap, s, SOAP_BLKLEN, c)) + { if (soap->error != SOAP_EOM) + return soap->error; + soap->error = SOAP_OK; + } + else + break; + } + n = tp->size + soap->blist->size; + if (!(s = (char*)SOAP_MALLOC(soap, n))) + return soap->error = SOAP_EOM; + if (tp->value) + { memcpy(s, tp->value, tp->size); + SOAP_FREE(soap, tp->value); + } + soap_save_block(soap, s + tp->size, 0); + tp->value = s; + tp->size = n; +#endif + } + do c = soap_get1(soap); + while (soap_blank(c)); + tp->visible = 2; /* seen this attribute w/ value */ +#ifdef WITH_DOM + if (att) + (*att)->data = soap_strdup(soap, tp->value); +#endif + } + else + tp->visible = 1; /* seen this attribute w/o value */ +#ifdef WITH_DOM + if (att) + att = &(*att)->next; +#endif + if (t && tp->value) + { if (soap_push_namespace(soap, t, tp->value)) + return soap->error; + } + } +#ifdef WITH_DOM + if (att) + { soap->dom->nstr = soap_current_namespace(soap, soap->tag); + for (att = &soap->dom->atts; *att; att = &(*att)->next) + (*att)->nstr = soap_current_namespace(soap, (*att)->name); + } +#endif + if ((int)c == EOF) + return soap->error = SOAP_EOF; + if (!(soap->body = (c != '/'))) + do c = soap_get1(soap); + while (soap_blank(c)); +#ifdef WITH_DOM + if (soap->mode & SOAP_XML_DOM) + { if (!soap->body && soap->dom->prnt) + soap->dom = soap->dom->prnt; + } +#endif + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible && tp->value) + { +#ifndef WITH_NOIDREF + if (!strcmp(tp->name, "id")) + { if (soap->version > 0 + || (soap->mode & SOAP_XML_GRAPH)) + { *soap->id = '#'; + strncpy(soap->id + 1, tp->value, sizeof(soap->id) - 2); + soap->id[sizeof(soap->id)-1] = '\0'; + } + } + else if (!strcmp(tp->name, "href")) + { if (soap->version == 1 + || (soap->mode & SOAP_XML_GRAPH) + || (soap->mode & SOAP_ENC_MTOM)) + { strncpy(soap->href, tp->value, sizeof(soap->href) - 1); + soap->href[sizeof(soap->href)-1] = '\0'; + } + } + else +#endif + if (!soap_match_tag(soap, tp->name, "xsi:type")) + { strncpy(soap->type, tp->value, sizeof(soap->type) - 1); + soap->type[sizeof(soap->type)-1] = '\0'; + } + else if ((!soap_match_tag(soap, tp->name, "xsi:null") + || !soap_match_tag(soap, tp->name, "xsi:nil")) + && (!strcmp(tp->value, "1") + || !strcmp(tp->value, "true"))) + { soap->null = 1; + } + else if (soap->version == 1) + { if (!soap_match_tag(soap, tp->name, "SOAP-ENC:arrayType")) + { s = soap_strrchr(tp->value, '['); + if (s && (size_t)(s - tp->value) < sizeof(soap->arrayType)) + { strncpy(soap->arrayType, tp->value, s - tp->value); + soap->arrayType[s - tp->value] = '\0'; + strncpy(soap->arraySize, s, sizeof(soap->arraySize) - 1); + } + else + strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1); + soap->arraySize[sizeof(soap->arrayType)-1] = '\0'; + soap->arrayType[sizeof(soap->arrayType)-1] = '\0'; + } + else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:offset")) + strncpy(soap->arrayOffset, tp->value, sizeof(soap->arrayOffset)); + else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:position")) + soap->position = soap_getposition(tp->value, soap->positions); + else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:root")) + soap->root = ((!strcmp(tp->value, "1") || !strcmp(tp->value, "true"))); + else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand") + && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true"))) + soap->mustUnderstand = 1; + else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:actor")) + { if ((!soap->actor || strcmp(soap->actor, tp->value)) + && strcmp(tp->value, "http://schemas.xmlsoap.org/soap/actor/next")) + soap->other = 1; + } + } + else if (soap->version == 2) + { if (!strcmp(tp->name, "ref") + || !soap_match_tag(soap, tp->name, "SOAP-ENC:ref")) + { *soap->href = '#'; + strncpy(soap->href + 1, tp->value, sizeof(soap->href) - 2); + soap->href[sizeof(soap->href)-1] = '\0'; + } + else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:itemType")) + strncpy(soap->arrayType, tp->value, sizeof(soap->arrayType) - 1); + else if (!soap_match_tag(soap, tp->name, "SOAP-ENC:arraySize")) + strncpy(soap->arraySize, tp->value, sizeof(soap->arraySize) - 1); + else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:mustUnderstand") + && (!strcmp(tp->value, "1") || !strcmp(tp->value, "true"))) + soap->mustUnderstand = 1; + else if (!soap_match_tag(soap, tp->name, "SOAP-ENV:role")) + { if ((!soap->actor || strcmp(soap->actor, tp->value)) + && strcmp(tp->value, "http://www.w3.org/2003/05/soap-envelope/role/next")) + soap->other = 1; + } + } + } + } + return soap->error = SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_retry(struct soap *soap) +{ soap->error = SOAP_OK; + soap_revert(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_revert(struct soap *soap) +{ if (!soap->peeked) + { soap->peeked = 1; + if (soap->body) + soap->level--; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Reverting last element (level=%u)\n", soap->level)); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_string_out(struct soap *soap, const char *s, int flag) +{ register const char *t; + register soap_wchar c; + register soap_wchar mask = 0xFFFFFF80UL; +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { soap->dom->data = soap_strdup(soap, s); + return SOAP_OK; + } +#endif + if (soap->mode & SOAP_C_UTFSTRING) + mask = 0; + t = s; + while ((c = *t++)) + { switch (c) + { + case 0x09: + if (flag) + { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, " ", 5)) + return soap->error; + s = t; + } + break; + case 0x0A: + if (flag || !(soap->mode & SOAP_XML_CANONICAL)) + { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, " ", 5)) + return soap->error; + s = t; + } + break; + case 0x0D: + if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, " ", 5)) + return soap->error; + s = t; + break; + case '&': + if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "&", 5)) + return soap->error; + s = t; + break; + case '<': + if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, "<", 4)) + return soap->error; + s = t; + break; + case '>': + if (!flag) + { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, ">", 4)) + return soap->error; + s = t; + } + break; + case '"': + if (flag) + { if (soap_send_raw(soap, s, t - s - 1) || soap_send_raw(soap, """, 6)) + return soap->error; + s = t; + } + break; + default: +#ifndef WITH_LEANER +#ifdef HAVE_MBTOWC + if (soap->mode & SOAP_C_MBSTRING) + { wchar_t wc; + register int m = mbtowc(&wc, t - 1, MB_CUR_MAX); + if (m > 0 && wc != c) + { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, wc)) + return soap->error; + s = t += m - 1; + continue; + } + } +#endif +#endif + if ((c & mask) || !(c & 0xFFFFFFE0UL)) + { if (soap_send_raw(soap, s, t - s - 1) || soap_pututf8(soap, (unsigned char)c)) + return soap->error; + s = t; + } + } + } + return soap_send_raw(soap, s, t - s - 1); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_string_in(struct soap *soap, int flag, long minlen, long maxlen) +{ register char *s; + char *t = NULL; + register size_t i; + register long l = 0; + register int n = 0; + register int m = 0; + register soap_wchar c; +#if !defined(WITH_LEANER) && defined(HAVE_WCTOMB) + char buf[MB_LEN_MAX > 8 ? MB_LEN_MAX : 8]; +#else + char buf[8]; +#endif + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading string content\n")); + if (soap->peeked) + { if (!soap->body) + return NULL; + if (*soap->tag) + { +#ifndef WITH_LEAN + struct soap_attribute *tp; + t = soap->tmpbuf; + *t = '<'; + t[sizeof(soap->tmpbuf)-1] = '\0'; + strncpy(t + 1, soap->tag, sizeof(soap->tmpbuf) - 2); + t += strlen(t); + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible) + { if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2) + break; + *t++ = ' '; + strcpy(t, tp->name); + t += strlen(t); + if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2) + break; + if (tp->value) + { *t++ = '='; + *t++ = '"'; + strcpy(t, tp->value); + t += strlen(t); + *t++ = '"'; + } + } + } + *t++ = '>'; + *t = '\0'; + t = soap->tmpbuf; + m = (int)strlen(soap->tmpbuf); +#endif + n = 1; + soap->peeked = 0; + } + } +#ifdef WITH_CDATA + if (!flag) + { register int state = 0; +#ifdef WITH_FAST + soap->labidx = 0; /* use look-aside buffer */ +#else + if (soap_new_block(soap)) + return NULL; +#endif + for (;;) + { +#ifdef WITH_FAST + register size_t k; + if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */ + return NULL; + s = soap->labbuf + soap->labidx; /* space to populate */ + k = soap->lablen - soap->labidx; /* number of bytes available */ + soap->labidx = soap->lablen; /* claim this space */ +#else + register size_t k = SOAP_BLKLEN; + if (!(s = (char*)soap_push_block(soap, k))) + return NULL; +#endif + for (i = 0; i < k; i++) + { if (m > 0) + { *s++ = *t++; /* copy multibyte characters */ + m--; + continue; + } + c = soap_getchar(soap); + if ((int)c == EOF) + goto end; + if (c >= 0x80 && !(soap->mode & SOAP_ENC_LATIN)) + { soap_unget(soap, c); + c = soap_getutf8(soap); + if (soap->mode & SOAP_C_UTFSTRING) + { if ((c & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP) + { c &= 0x7FFFFFFF; + t = buf; + if (c < 0x0800) + *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); + else + { if (c < 0x010000) + *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + else + { if (c < 0x200000) + *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + else + { if (c < 0x04000000) + *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + else + { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + } + *t++ = (char)(0x80 | (c & 0x3F)); + m = (int)(t - buf) - 1; + t = buf; + *s++ = *t++; + continue; + } + } + } + switch (state) + { case 1: + if (c == ']') + state = 4; + *s++ = c; + continue; + case 2: + if (c == '-') + state = 6; + *s++ = c; + continue; + case 3: + if (c == '?') + state = 8; + *s++ = c; + continue; + /* CDATA */ + case 4: + if (c == ']') + state = 5; + else + state = 1; + *s++ = c; + continue; + case 5: + if (c == '>') + state = 0; + else + state = 1; + *s++ = c; + continue; + /* comment */ + case 6: + if (c == '-') + state = 7; + else + state = 2; + *s++ = c; + continue; + case 7: + if (c == '>') + state = 0; + else + state = 2; + *s++ = c; + continue; + /* PI */ + case 8: + if (c == '>') + state = 0; + else + state = 3; + *s++ = c; + continue; + } + switch (c) + { + case '/': + if (n > 0) + { c = soap_getchar(soap); + if (c == '>') + n--; + soap_unget(soap, c); + } + *s++ = '/'; + break; + case '<': + c = soap_getchar(soap); + if (c == '/') + { if (n == 0) + { c = SOAP_TT; + goto end; + } + n--; + } + else if (c == '!') + { c = soap_getchar(soap); + if (c == '[') + { do c = soap_getchar(soap); + while ((int)c != EOF && c != '['); + if ((int)c == EOF) + goto end; + t = (char*)"![CDATA["; + m = 8; + state = 1; + } + else if (c == '-') + { if ((c = soap_getchar(soap)) == '-') + state = 2; + t = (char*)"!-"; + m = 2; + soap_unget(soap, c); + } + else + { t = (char*)"!"; + m = 1; + soap_unget(soap, c); + } + *s++ = '<'; + break; + } + else if (c == '?') + state = 3; + else + n++; + soap_unget(soap, c); + *s++ = '<'; + break; + case '>': + *s++ = '>'; + break; + case '"': + *s++ = '"'; + break; + default: +#ifndef WITH_LEANER +#ifdef HAVE_WCTOMB + if (soap->mode & SOAP_C_MBSTRING) + { m = wctomb(buf, c & 0x7FFFFFFF); + if (m >= 1 && m <= (int)MB_CUR_MAX) + { t = buf; + *s++ = *t++; + m--; + } + else + { *s++ = SOAP_UNKNOWN_CHAR; + m = 0; + } + } + else +#endif +#endif + *s++ = (char)(c & 0xFF); + } + l++; + if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); + soap->error = SOAP_LENGTH; + return NULL; + } + } + } + } +#endif +#ifdef WITH_FAST + soap->labidx = 0; /* use look-aside buffer */ +#else + if (soap_new_block(soap)) + return NULL; +#endif + for (;;) + { +#ifdef WITH_FAST + register size_t k; + if (soap_append_lab(soap, NULL, 0)) /* allocate more space in look-aside buffer if necessary */ + return NULL; + s = soap->labbuf + soap->labidx; /* space to populate */ + k = soap->lablen - soap->labidx; /* number of bytes available */ + soap->labidx = soap->lablen; /* claim this space */ +#else + register size_t k = SOAP_BLKLEN; + if (!(s = (char*)soap_push_block(soap, k))) + return NULL; +#endif + for (i = 0; i < k; i++) + { if (m > 0) + { *s++ = *t++; /* copy multibyte characters */ + m--; + continue; + } + if (soap->mode & SOAP_C_UTFSTRING) + { if (((c = soap_get(soap)) & 0x80000000) && c >= -0x7FFFFF80 && c < SOAP_AP) + { c &= 0x7FFFFFFF; + t = buf; + if (c < 0x0800) + *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); + else + { if (c < 0x010000) + *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + else + { if (c < 0x200000) + *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + else + { if (c < 0x04000000) + *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + else + { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + } + *t++ = (char)(0x80 | (c & 0x3F)); + m = (int)(t - buf) - 1; + t = buf; + *s++ = *t++; + continue; + } + } + else + c = soap_getutf8(soap); + switch (c) + { + case SOAP_TT: + if (n == 0) + goto end; + n--; + *s++ = '<'; + t = (char*)"/"; + m = 1; + break; + case SOAP_LT: + n++; + *s++ = '<'; + break; + case SOAP_GT: + *s++ = '>'; + break; + case SOAP_QT: + *s++ = '"'; + break; + case SOAP_AP: + *s++ = '\''; + break; + case '/': + if (n > 0) + { c = soap_get(soap); + if (c == SOAP_GT) + n--; + soap_unget(soap, c); + } + *s++ = '/'; + break; + case (soap_wchar)('<' | 0x80000000): + if (flag) + *s++ = '<'; + else + { *s++ = '&'; + t = (char*)"lt;"; + m = 3; + } + break; + case (soap_wchar)('>' | 0x80000000): + if (flag) + *s++ = '>'; + else + { *s++ = '&'; + t = (char*)"gt;"; + m = 3; + } + break; + case (soap_wchar)('&' | 0x80000000): + if (flag) + *s++ = '&'; + else + { *s++ = '&'; + t = (char*)"amp;"; + m = 4; + } + break; + case (soap_wchar)('"' | 0x80000000): + if (flag) + *s++ = '"'; + else + { *s++ = '&'; + t = (char*)"quot;"; + m = 5; + } + break; + case (soap_wchar)('\'' | 0x80000000): + if (flag) + *s++ = '\''; + else + { *s++ = '&'; + t = (char*)"apos;"; + m = 5; + } + break; + default: + if ((int)c == EOF) + goto end; +#ifndef WITH_LEANER +#ifdef HAVE_WCTOMB + if (soap->mode & SOAP_C_MBSTRING) + { m = wctomb(buf, c & 0x7FFFFFFF); + if (m >= 1 && m <= (int)MB_CUR_MAX) + { t = buf; + *s++ = *t++; + m--; + } + else + { *s++ = SOAP_UNKNOWN_CHAR; + m = 0; + } + } + else +#endif +#endif + *s++ = (char)(c & 0xFF); + } + l++; + if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); + soap->error = SOAP_LENGTH; + return NULL; + } + } + } +end: + soap_unget(soap, c); + *s = '\0'; +#ifdef WITH_FAST + t = soap_strdup(soap, soap->labbuf); +#else + soap_size_block(soap, i+1); + t = soap_save_block(soap, NULL, 0); +#endif + if ((soap->mode & SOAP_XML_STRICT) && l < minlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen)); + soap->error = SOAP_LENGTH; + return NULL; + } +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { if (flag == 3) + soap->dom->tail = t; + else + soap->dom->data = t; + } +#endif + if (flag == 2) + if (soap_s2QName(soap, t, &t)) + return NULL; + return t; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_wstring_out(struct soap *soap, const wchar_t *s, int flag) +{ const char *t; + char tmp; + register soap_wchar c; +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + { wchar_t *r = (wchar_t*)s; + int n = 1; + while (*r++) + n++; + soap->dom->wide = r = (wchar_t*)soap_malloc(soap, n * sizeof(wchar_t)); + while (n--) + *r++ = *s++; + return SOAP_OK; + } +#endif + while ((c = *s++)) + { switch (c) + { + case 0x09: + if (flag) + t = " "; + else + t = "\t"; + break; + case 0x0A: + if (flag || !(soap->mode & SOAP_XML_CANONICAL)) + t = " "; + else + t = "\n"; + break; + case 0x0D: + t = " "; + break; + case '&': + t = "&"; + break; + case '<': + t = "<"; + break; + case '>': + if (flag) + t = ">"; + else + t = ">"; + break; + case '"': + if (flag) + t = """; + else + t = "\""; + break; + default: + if (c >= 0x20 && c < 0x80) + { tmp = (char)c; + if (soap_send_raw(soap, &tmp, 1)) + return soap->error; + } + else if (soap_pututf8(soap, (unsigned long)c)) + return soap->error; + continue; + } + if (soap_send(soap, t)) + return soap->error; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +wchar_t * +SOAP_FMAC2 +soap_wstring_in(struct soap *soap, int flag, long minlen, long maxlen) +{ wchar_t *s; + register int i, n = 0; + register long l = 0; + register soap_wchar c; + char *t = NULL; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Reading wide string content\n")); + if (soap->peeked) + { if (!soap->body) + return NULL; + if (*soap->tag) + { +#ifndef WITH_LEAN + struct soap_attribute *tp; + t = soap->tmpbuf; + *t = '<'; + t[sizeof(soap->tmpbuf)-1] = '\0'; + strncpy(t + 1, soap->tag, sizeof(soap->tmpbuf) - 2); + t += strlen(t); + for (tp = soap->attributes; tp; tp = tp->next) + { if (tp->visible) + { if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2) + break; + *t++ = ' '; + strcpy(t, tp->name); + t += strlen(t); + if (t >= soap->tmpbuf + sizeof(soap->tmpbuf) - 2) + break; + if (tp->value) + { *t++ = '='; + *t++ = '"'; + strcpy(t, tp->value); + t += strlen(t); + *t++ = '"'; + } + } + } + *t++ = '>'; + *t = '\0'; + t = soap->tmpbuf; +#endif + n = 1; + soap->peeked = 0; + } + } + if (soap_new_block(soap)) + return NULL; + for (;;) + { if (!(s = (wchar_t*)soap_push_block(soap, sizeof(wchar_t)*SOAP_BLKLEN))) + return NULL; + for (i = 0; i < SOAP_BLKLEN; i++) + { if (t) + { *s++ = (wchar_t)*t++; + if (!*t) + t = NULL; + continue; + } + c = soap_getutf8(soap); + switch (c) + { + case SOAP_TT: + if (n == 0) + goto end; + n--; + *s++ = '<'; + soap_unget(soap, '/'); + break; + case SOAP_LT: + n++; + *s++ = '<'; + break; + case SOAP_GT: + *s++ = '>'; + break; + case SOAP_QT: + *s++ = '"'; + break; + case SOAP_AP: + *s++ = '\''; + break; + case '/': + if (n > 0) + { c = soap_getutf8(soap); + if (c == SOAP_GT) + n--; + soap_unget(soap, c); + } + *s++ = '/'; + break; + case '<': + if (flag) + *s++ = (soap_wchar)'<'; + else + { *s++ = (soap_wchar)'&'; + t = "lt;"; + } + break; + case '>': + if (flag) + *s++ = (soap_wchar)'>'; + else + { *s++ = (soap_wchar)'&'; + t = "gt;"; + } + break; + case '"': + if (flag) + *s++ = (soap_wchar)'"'; + else + { *s++ = (soap_wchar)'&'; + t = "quot;"; + } + break; + default: + if ((int)c == EOF) + goto end; + *s++ = (wchar_t)c & 0x7FFFFFFF; + } + l++; + if ((soap->mode & SOAP_XML_STRICT) && maxlen >= 0 && l > maxlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too long: maxlen=%ld\n", maxlen)); + soap->error = SOAP_LENGTH; + return NULL; + } + } + } +end: + soap_unget(soap, c); + *s = '\0'; + soap_size_block(soap, sizeof(wchar_t) * (i + 1)); + if ((soap->mode & SOAP_XML_STRICT) && l < minlen) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "String too short: %ld chars, minlen=%ld\n", l, minlen)); + soap->error = SOAP_LENGTH; + return NULL; + } + s = (wchar_t*)soap_save_block(soap, NULL, 0); +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + soap->dom->wide = s; +#endif + return s; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_int2s(struct soap *soap, int n) +{ return soap_long2s(soap, (long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outint(struct soap *soap, const char *tag, int id, const int *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_long2s(soap, (long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2int(struct soap *soap, const char *s, int *p) +{ if (s) + { char *r; +#ifndef WITH_NOIO +#ifndef WITH_LEAN + soap_reset_errno; +#endif +#endif + *p = (int)soap_strtol(s, &r, 10); + if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r +#ifndef WITH_NOIO +#ifndef WITH_LEAN + || soap_errno == SOAP_ERANGE +#endif +#endif + ) + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int * +SOAP_FMAC2 +soap_inint(struct soap *soap, const char *tag, int *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":int") + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (int*)soap_id_enter(soap, soap->id, p, t, sizeof(int), 0, NULL, NULL, NULL); + if (*soap->href) + p = (int*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(int), 0, NULL); + else if (p) + { if (soap_s2int(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_long2s(struct soap *soap, long n) +{ sprintf(soap->tmpbuf, "%ld", n); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outlong(struct soap *soap, const char *tag, int id, const long *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_long2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2long(struct soap *soap, const char *s, long *p) +{ if (s) + { char *r; +#ifndef WITH_NOIO +#ifndef WITH_LEAN + soap_reset_errno; +#endif +#endif + *p = soap_strtol(s, &r, 10); + if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r +#ifndef WITH_NOIO +#ifndef WITH_LEAN + || soap_errno == SOAP_ERANGE +#endif +#endif + ) + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +long * +SOAP_FMAC2 +soap_inlong(struct soap *soap, const char *tag, long *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":int") + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (long*)soap_id_enter(soap, soap->id, p, t, sizeof(long), 0, NULL, NULL, NULL); + if (*soap->href) + p = (long*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(long), 0, NULL); + else if (p) + { if (soap_s2long(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_LONG642s(struct soap *soap, LONG64 n) +{ sprintf(soap->tmpbuf, SOAP_LONG_FORMAT, n); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outLONG64(struct soap *soap, const char *tag, int id, const LONG64 *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_LONG642s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2LONG64(struct soap *soap, const char *s, LONG64 *p) +{ if (s) + { +#ifdef HAVE_STRTOLL + char *r; +#ifndef WITH_NOIO +#ifndef WITH_LEAN + soap_reset_errno; +#endif +#endif + *p = strtoll(s, &r, 10); + if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r +#ifndef WITH_NOIO +#ifndef WITH_LEAN + || soap_errno == SOAP_ERANGE +#endif +#endif + ) +#else +# ifdef HAVE_SSCANF + if (sscanf(s, SOAP_LONG_FORMAT, p) != 1) +# endif +#endif + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +LONG64 * +SOAP_FMAC2 +soap_inLONG64(struct soap *soap, const char *tag, LONG64 *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":integer") + && soap_match_tag(soap, soap->type, ":positiveInteger") + && soap_match_tag(soap, soap->type, ":negativeInteger") + && soap_match_tag(soap, soap->type, ":nonPositiveInteger") + && soap_match_tag(soap, soap->type, ":nonNegativeInteger") + && soap_match_tag(soap, soap->type, ":long") + && soap_match_tag(soap, soap->type, ":int") + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (LONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(LONG64), 0, NULL, NULL, NULL); + if (*soap->href) + p = (LONG64*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(LONG64), 0, NULL); + else if (p) + { if (soap_s2LONG64(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_byte2s(struct soap *soap, char n) +{ return soap_long2s(soap, (long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outbyte(struct soap *soap, const char *tag, int id, const char *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_long2s(soap, (long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2byte(struct soap *soap, const char *s, char *p) +{ if (s) + { long n; + char *r; + n = soap_strtol(s, &r, 10); + if (s == r || *r || n < -128 || n > 127) + soap->error = SOAP_TYPE; + *p = (char)n; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_inbyte(struct soap *soap, const char *tag, char *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (char*)soap_id_enter(soap, soap->id, p, t, sizeof(char), 0, NULL, NULL, NULL); + if (*soap->href) + p = (char*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(char), 0, NULL); + else if (p) + { if (soap_s2byte(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_short2s(struct soap *soap, short n) +{ return soap_long2s(soap, (long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outshort(struct soap *soap, const char *tag, int id, const short *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_long2s(soap, (long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2short(struct soap *soap, const char *s, short *p) +{ if (s) + { long n; + char *r; + n = soap_strtol(s, &r, 10); + if (s == r || *r || n < -32768 || n > 32767) + soap->error = SOAP_TYPE; + *p = (short)n; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +short * +SOAP_FMAC2 +soap_inshort(struct soap *soap, const char *tag, short *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (short*)soap_id_enter(soap, soap->id, p, t, sizeof(short), 0, NULL, NULL, NULL); + if (*soap->href) + p = (short*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(short), 0, NULL); + else if (p) + { if (soap_s2short(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_float2s(struct soap *soap, float n) +{ char *s, *t; + if (soap_isnan((double)n)) + return "NaN"; + if (soap_ispinff(n)) + return "INF"; + if (soap_isninff(n)) + return "-INF"; + s = soap->tmpbuf; + sprintf(soap->tmpbuf, soap->float_format, n); + t = strchr(s, ','); /* convert decimal comma to DP */ + if (t) + *t = '.'; + return s; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outfloat(struct soap *soap, const char *tag, int id, const float *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_float2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2float(struct soap *soap, const char *s, float *p) +{ if (s) + { if (!*s) + return soap->error = SOAP_TYPE; + if (!soap_tag_cmp(s, "INF")) + *p = FLT_PINFTY; + else if (!soap_tag_cmp(s, "+INF")) + *p = FLT_PINFTY; + else if (!soap_tag_cmp(s, "-INF")) + *p = FLT_NINFTY; + else if (!soap_tag_cmp(s, "NaN")) + *p = FLT_NAN; + else + { +/* On some systems, strtof appears to be broken or doesn't link: use with caution */ +#if defined(HAVE_STRTOF) + char *r; + *p = strtof((char*)s, &r); + if (*r) +#elif defined(HAVE_STRTOD) + char *r; + *p = (float)strtod(s, &r); + if (*r) +#endif +#ifdef HAVE_SSCANF + if (sscanf(s, "%g", p) != 1) + soap->error = SOAP_TYPE; +#else + soap->error = SOAP_TYPE; +#endif + } + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static int soap_isnumeric(struct soap *soap, const char *type) +{ if (soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":float") + && soap_match_tag(soap, soap->type, ":double") + && soap_match_tag(soap, soap->type, ":decimal") + && soap_match_tag(soap, soap->type, ":integer") + && soap_match_tag(soap, soap->type, ":positiveInteger") + && soap_match_tag(soap, soap->type, ":negativeInteger") + && soap_match_tag(soap, soap->type, ":nonPositiveInteger") + && soap_match_tag(soap, soap->type, ":nonNegativeInteger") + && soap_match_tag(soap, soap->type, ":long") + && soap_match_tag(soap, soap->type, ":int") + && soap_match_tag(soap, soap->type, ":short") + && soap_match_tag(soap, soap->type, ":byte") + && soap_match_tag(soap, soap->type, ":unsignedLong") + && soap_match_tag(soap, soap->type, ":unsignedInt") + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return SOAP_ERR; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +float * +SOAP_FMAC2 +soap_infloat(struct soap *soap, const char *tag, float *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type != '\0' && soap_isnumeric(soap, type)) + return NULL; +#endif + p = (float*)soap_id_enter(soap, soap->id, p, t, sizeof(float), 0, NULL, NULL, NULL); + if (*soap->href) + p = (float*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(float), 0, NULL); + else if (p) + { if (soap_s2float(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_double2s(struct soap *soap, double n) +{ char *s, *t; + if (soap_isnan(n)) + return "NaN"; + if (soap_ispinfd(n)) + return "INF"; + if (soap_isninfd(n)) + return "-INF"; + s = soap->tmpbuf; + sprintf(soap->tmpbuf, soap->double_format, n); + t = strchr(s, ','); /* convert decimal comma to DP */ + if (t) + *t = '.'; + return s; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outdouble(struct soap *soap, const char *tag, int id, const double *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_double2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2double(struct soap *soap, const char *s, double *p) +{ if (s) + { if (!*s) + return soap->error = SOAP_TYPE; + if (!soap_tag_cmp(s, "INF")) + *p = DBL_PINFTY; + else if (!soap_tag_cmp(s, "+INF")) + *p = DBL_PINFTY; + else if (!soap_tag_cmp(s, "-INF")) + *p = DBL_NINFTY; + else if (!soap_tag_cmp(s, "NaN")) + *p = DBL_NAN; + else + { +#ifdef HAVE_STRTOD + char *r; + *p = strtod(s, &r); + if (*r) +#endif +#ifdef HAVE_SSCANF + if (sscanf(s, "%lg", p) != 1) + soap->error = SOAP_TYPE; +#else + soap->error = SOAP_TYPE; +#endif + } + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +double * +SOAP_FMAC2 +soap_indouble(struct soap *soap, const char *tag, double *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type != '\0' && soap_isnumeric(soap, type)) + return NULL; +#endif + p = (double*)soap_id_enter(soap, soap->id, p, t, sizeof(double), 0, NULL, NULL, NULL); + if (*soap->href) + p = (double*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(double), 0, NULL); + else if (p) + { if (soap_s2double(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_unsignedByte2s(struct soap *soap, unsigned char n) +{ return soap_unsignedLong2s(soap, (unsigned long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outunsignedByte(struct soap *soap, const char *tag, int id, const unsigned char *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2unsignedByte(struct soap *soap, const char *s, unsigned char *p) +{ if (s) + { unsigned long n; + char *r; + n = soap_strtoul(s, &r, 10); + if (s == r || *r || n > 255) + soap->error = SOAP_TYPE; + *p = (unsigned char)n; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +unsigned char * +SOAP_FMAC2 +soap_inunsignedByte(struct soap *soap, const char *tag, unsigned char *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (unsigned char*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned char), 0, NULL, NULL, NULL); + if (*soap->href) + p = (unsigned char*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned char), 0, NULL); + else if (p) + { if (soap_s2unsignedByte(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_unsignedShort2s(struct soap *soap, unsigned short n) +{ return soap_unsignedLong2s(soap, (unsigned long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outunsignedShort(struct soap *soap, const char *tag, int id, const unsigned short *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2unsignedShort(struct soap *soap, const char *s, unsigned short *p) +{ if (s) + { unsigned long n; + char *r; + n = soap_strtoul(s, &r, 10); + if (s == r || *r || n > 65535) + soap->error = SOAP_TYPE; + *p = (unsigned short)n; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +unsigned short * +SOAP_FMAC2 +soap_inunsignedShort(struct soap *soap, const char *tag, unsigned short *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (unsigned short*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned short), 0, NULL, NULL, NULL); + if (*soap->href) + p = (unsigned short*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned short), 0, NULL); + else if (p) + { if (soap_s2unsignedShort(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_unsignedInt2s(struct soap *soap, unsigned int n) +{ return soap_unsignedLong2s(soap, (unsigned long)n); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outunsignedInt(struct soap *soap, const char *tag, int id, const unsigned int *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_unsignedLong2s(soap, (unsigned long)*p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2unsignedInt(struct soap *soap, const char *s, unsigned int *p) +{ if (s) + { char *r; +#ifndef WITH_NOIO +#ifndef WITH_LEAN + soap_reset_errno; +#endif +#endif + *p = (unsigned int)soap_strtoul(s, &r, 10); + if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r +#ifndef WITH_NOIO +#ifndef WITH_LEAN + || soap_errno == SOAP_ERANGE +#endif +#endif + ) + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +unsigned int * +SOAP_FMAC2 +soap_inunsignedInt(struct soap *soap, const char *tag, unsigned int *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":unsignedInt") + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (unsigned int*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned int), 0, NULL, NULL, NULL); + if (*soap->href) + p = (unsigned int*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned int), 0, NULL); + else if (p) + { if (soap_s2unsignedInt(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_unsignedLong2s(struct soap *soap, unsigned long n) +{ sprintf(soap->tmpbuf, "%lu", n); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outunsignedLong(struct soap *soap, const char *tag, int id, const unsigned long *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_unsignedLong2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2unsignedLong(struct soap *soap, const char *s, unsigned long *p) +{ if (s) + { char *r; +#ifndef WITH_NOIO +#ifndef WITH_LEAN + soap_reset_errno; +#endif +#endif + *p = soap_strtoul(s, &r, 10); + if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r +#ifndef WITH_NOIO +#ifndef WITH_LEAN + || soap_errno == SOAP_ERANGE +#endif +#endif + ) + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +unsigned long * +SOAP_FMAC2 +soap_inunsignedLong(struct soap *soap, const char *tag, unsigned long *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; +#ifndef WITH_LEAN + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":unsignedInt") + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } +#endif + p = (unsigned long*)soap_id_enter(soap, soap->id, p, t, sizeof(unsigned long), 0, NULL, NULL, NULL); + if (*soap->href) + p = (unsigned long*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(unsigned long), 0, NULL); + else if (p) + { if (soap_s2unsignedLong(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_ULONG642s(struct soap *soap, ULONG64 n) +{ sprintf(soap->tmpbuf, SOAP_ULONG_FORMAT, n); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outULONG64(struct soap *soap, const char *tag, int id, const ULONG64 *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_ULONG642s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2ULONG64(struct soap *soap, const char *s, ULONG64 *p) +{ if (s) + { +#ifdef HAVE_STRTOULL + char *r; +#ifndef WITH_NOIO +#ifndef WITH_LEAN + soap_reset_errno; +#endif +#endif + *p = strtoull(s, &r, 10); + if ((s == r && (soap->mode & SOAP_XML_STRICT)) || *r +#ifndef WITH_NOIO +#ifndef WITH_LEAN + || soap_errno == SOAP_ERANGE +#endif +#endif + ) +#else +# ifdef HAVE_SSCANF + if (sscanf(s, SOAP_ULONG_FORMAT, p) != 1) +# endif +#endif + soap->error = SOAP_TYPE; + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +ULONG64 * +SOAP_FMAC2 +soap_inULONG64(struct soap *soap, const char *tag, ULONG64 *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":positiveInteger") + && soap_match_tag(soap, soap->type, ":nonNegativeInteger") + && soap_match_tag(soap, soap->type, ":unsignedLong") + && soap_match_tag(soap, soap->type, ":unsignedInt") + && soap_match_tag(soap, soap->type, ":unsignedShort") + && soap_match_tag(soap, soap->type, ":unsignedByte")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } + p = (ULONG64*)soap_id_enter(soap, soap->id, p, t, sizeof(ULONG64), 0, NULL, NULL, NULL); + if (*soap->href) + p = (ULONG64*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(ULONG64), 0, NULL); + else if (p) + { if (soap_s2ULONG64(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2string(struct soap *soap, const char *s, char **t) +{ *t = NULL; + if (s) + { if (!(*t = soap_strdup(soap, s))) + return soap->error = SOAP_EOM; + if (!(soap->mode & (SOAP_ENC_LATIN | SOAP_C_UTFSTRING))) + { /* TODO: consider truncating UTF8 to ASCII for regular XML attribute strings? */ + } + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2QName(struct soap *soap, const char *s, char **t) +{ *t = NULL; + if (s) + { soap->labidx = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Normalized namespace(s) of QNames '%s'", s)); + /* convert (by prefix normalize prefix) all QNames in s */ + for (;;) + { size_t n; + struct soap_nlist *np; + register const char *p; + /* skip blanks */ + while (*s && soap_blank(*s)) + s++; + if (!*s) + break; + /* find next QName */ + n = 1; + while (s[n] && !soap_blank(s[n])) + n++; + np = soap->nlist; + /* if there is no namespace stack, or prefix is "xml" then copy string */ + if (!np || !strncmp(s, "xml:", 4)) + { soap_append_lab(soap, s, n); + } + else /* we normalize the QName by replacing its prefix */ + { p = strchr(s, ':'); + if (p) + { size_t k = p - s; + while (np && (strncmp(np->id, s, k) || np->id[k])) + np = np->next; + p++; + } + else + { while (np && *np->id) + np = np->next; + p = s; + } + /* replace prefix */ + if (np) + { if (np->index >= 0 && soap->local_namespaces) + { const char *q = soap->local_namespaces[np->index].id; + if (q) + soap_append_lab(soap, q, strlen(q)); + } + else if (np->ns) + { soap_append_lab(soap, "\"", 1); + soap_append_lab(soap, np->ns, strlen(np->ns)); + soap_append_lab(soap, "\"", 1); + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "\nNamespace prefix of '%s' not defined (index=%d, URI=%s)\n", s, np->index, np->ns?np->ns:"")); + return soap->error = SOAP_NAMESPACE; + } + } + else /* no namespace: assume default "" namespace */ + { soap_append_lab(soap, "\"\"", 2); + } + soap_append_lab(soap, ":", 1); + soap_append_lab(soap, p, n - (p-s)); + } + /* advance to next and add spacing */ + s += n; + if (*s) + soap_append_lab(soap, " ", 1); + } + soap_append_lab(soap, SOAP_STR_EOS, 1); + *t = soap_strdup(soap, soap->labbuf); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, " into '%s'\n", *t)); + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_QName2s(struct soap *soap, const char *s) +{ const char *t = NULL; + if (s) + { soap->labidx = 0; + for (;;) + { size_t n; + /* skip blanks */ + while (*s && soap_blank(*s)) + s++; + if (!*s) + break; + /* find next QName */ + n = 1; + while (s[n] && !soap_blank(s[n])) + n++; + /* normal prefix: pass string as is */ + if (*s != '"') + { soap_append_lab(soap, s, n); +#ifndef WITH_LEAN + if ((soap->mode & SOAP_XML_CANONICAL)) + { const char *r = strchr(s, ':'); + if (r) + soap_utilize_ns(soap, s, r - s); + } +#endif + } + else /* URL-based string prefix */ + { const char *q; + s++; + q = strchr(s, '"'); + if (q) + { struct Namespace *p = soap->local_namespaces; + if (p) + { for (; p->id; p++) + { if (p->ns) + if (!soap_tag_cmp(s, p->ns)) + break; + if (p->in) + if (!soap_tag_cmp(s, p->in)) + break; + } + } + /* URL is in the namespace table? */ + if (p && p->id) + { soap_append_lab(soap, p->id, strlen(p->id)); + } + else /* not in namespace table: create xmlns binding */ + { char *r = soap_strdup(soap, s); + r[q-s] = '\0'; + sprintf(soap->tmpbuf, "xmlns:_%d", soap->idnum++); + soap_set_attr(soap, soap->tmpbuf, r); + soap_append_lab(soap, soap->tmpbuf + 6, strlen(soap->tmpbuf + 6)); + } + soap_append_lab(soap, q + 1, n - (q-s) - 1); + } + } + /* advance to next and add spacing */ + s += n; + if (*s) + soap_append_lab(soap, " ", 1); + } + soap_append_lab(soap, SOAP_STR_EOS, 1); + t = soap_strdup(soap, soap->labbuf); + } + return t; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2wchar(struct soap *soap, const char *s, wchar_t **t) +{ wchar_t *r; + if (!s) + *t = NULL; + else + { *t = r = (wchar_t*)soap_malloc(soap, sizeof(wchar_t) * (strlen(s) + 1)); + if (!r) + return soap->error; + if (soap->mode & SOAP_ENC_LATIN) + { while (*s) + *r++ = (wchar_t)*s++; + } + else + { /* Convert UTF8 to wchar */ + while (*s) + { register soap_wchar c, c1, c2, c3, c4; + c = *s++; + if (c < 0x80) + *r++ = (wchar_t)c; + else + { c1 = (soap_wchar)*s++ & 0x3F; + if (c < 0xE0) + *r++ = (wchar_t)(((soap_wchar)(c & 0x1F) << 6) | c1); + else + { c2 = (soap_wchar)*s++ & 0x3F; + if (c < 0xF0) + *r++ = (wchar_t)(((soap_wchar)(c & 0x0F) << 12) | (c1 << 6) | c2); + else + { c3 = (soap_wchar)*s++ & 0x3F; + if (c < 0xF8) + *r++ = (wchar_t)(((soap_wchar)(c & 0x07) << 18) | (c1 << 12) | (c2 << 6) | c3); + else + { c4 = (soap_wchar)*s++ & 0x3F; + if (c < 0xFC) + *r++ = (wchar_t)(((soap_wchar)(c & 0x03) << 24) | (c1 << 18) | (c2 << 12) | (c3 << 6) | c4); + else + *r++ = (wchar_t)(((soap_wchar)(c & 0x01) << 30) | (c1 << 24) | (c2 << 18) | (c3 << 12) | (c4 << 6) | (soap_wchar)(*s++ & 0x3F)); + } + } + } + } + } + } + *r = L'\0'; + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_wchar2s(struct soap *soap, const wchar_t *s) +{ register soap_wchar c; + register char *r, *t; + const wchar_t *q = s; + size_t n = 0; + while ((c = *q++)) + { if (c > 0 && c < 0x80) + n++; + else + n += 6; + } + r = t = (char*)soap_malloc(soap, n + 1); + if (r) + { /* Convert wchar to UTF8 */ + while ((c = *s++)) + { if (c > 0 && c < 0x80) + *t++ = (char)c; + else + { if (c < 0x0800) + *t++ = (char)(0xC0 | ((c >> 6) & 0x1F)); + else + { if (c < 0x010000) + *t++ = (char)(0xE0 | ((c >> 12) & 0x0F)); + else + { if (c < 0x200000) + *t++ = (char)(0xF0 | ((c >> 18) & 0x07)); + else + { if (c < 0x04000000) + *t++ = (char)(0xF8 | ((c >> 24) & 0x03)); + else + { *t++ = (char)(0xFC | ((c >> 30) & 0x01)); + *t++ = (char)(0x80 | ((c >> 24) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 18) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 12) & 0x3F)); + } + *t++ = (char)(0x80 | ((c >> 6) & 0x3F)); + } + *t++ = (char)(0x80 | (c & 0x3F)); + } + } + *t = '\0'; + } + return r; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outstring(struct soap *soap, const char *tag, int id, char *const*p, const char *type, int n) +{ id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n); + if (id < 0) + return soap->error; + if (!**p && (soap->mode & SOAP_C_NILSTRING)) + return soap_element_null(soap, tag, id, type); + if (soap_element_begin_out(soap, tag, id, type) + || soap_string_out(soap, *p, 0) + || soap_element_end_out(soap, tag)) + return soap->error; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char ** +SOAP_FMAC2 +soap_instring(struct soap *soap, const char *tag, char **p, const char *type, int t, int flag, long minlen, long maxlen) +{ if (soap_element_begin_in(soap, tag, 1, NULL)) + { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG) + return NULL; + soap->error = SOAP_OK; + } + if (!p) + { if (!(p = (char**)soap_malloc(soap, sizeof(char*)))) + return NULL; + } + if (soap->body) + { *p = soap_string_in(soap, flag, minlen, maxlen); + if (!*p || !(char*)soap_id_enter(soap, soap->id, *p, t, sizeof(char*), 0, NULL, NULL, NULL)) + return NULL; + if (!**p && tag && *tag == '-') + { soap->error = SOAP_NO_TAG; + return NULL; + } + } + else if (tag && *tag == '-') + { soap->error = SOAP_NO_TAG; + return NULL; + } + else if (soap->null) + *p = NULL; + else + *p = (char*)SOAP_STR_EOS; + if (*soap->href) + p = (char**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(char**), 0); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outwstring(struct soap *soap, const char *tag, int id, wchar_t *const*p, const char *type, int n) +{ id = soap_element_id(soap, tag, id, *p, NULL, 0, type, n); + if (id < 0) + return soap->error; + if (!**p && (soap->mode & SOAP_C_NILSTRING)) + return soap_element_null(soap, tag, id, type); + if (soap_element_begin_out(soap, tag, id, type) + || soap_wstring_out(soap, *p, 0) + || soap_element_end_out(soap, tag)) + return soap->error; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +wchar_t ** +SOAP_FMAC2 +soap_inwstring(struct soap *soap, const char *tag, wchar_t **p, const char *type, int t, long minlen, long maxlen) +{ if (soap_element_begin_in(soap, tag, 1, NULL)) + { if (!tag || *tag != '-' || soap->error != SOAP_NO_TAG) + return NULL; + soap->error = SOAP_OK; + } + if (!p) + { if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*)))) + return NULL; + } + if (soap->body) + { *p = soap_wstring_in(soap, 1, minlen, maxlen); + if (!*p || !(wchar_t*)soap_id_enter(soap, soap->id, *p, t, sizeof(wchar_t*), 0, NULL, NULL, NULL)) + return NULL; + if (!**p && tag && *tag == '-') + { soap->error = SOAP_NO_TAG; + return NULL; + } + } + else if (tag && *tag == '-') + { soap->error = SOAP_NO_TAG; + return NULL; + } + else if (soap->null) + *p = NULL; + else + *p = (wchar_t*)SOAP_STR_EOS; + if (*soap->href) + p = (wchar_t**)soap_id_lookup(soap, soap->href, (void**)p, t, sizeof(wchar_t**), 0); + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +time_t +SOAP_FMAC2 +soap_timegm(struct tm *T) +{ +#if defined(HAVE_TIMEGM) + return timegm(T); +#else + time_t t, g, z; + struct tm tm; + t = mktime(T); + if (t == -1) + return -1; +#ifdef HAVE_GMTIME_R + gmtime_r(&t, &tm); +#else + tm = *gmtime(&t); +#endif + tm.tm_isdst = 0; + g = mktime(&tm); + if (g == -1) + return -1; + z = g - t; + return t - z; +#endif +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_dateTime2s(struct soap *soap, time_t n) +{ struct tm T, *pT = &T; +#if defined(HAVE_GMTIME_R) + if (gmtime_r(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); + /* The following defines were added for VxWorks*/ +#elif defined(HAVE_PGMTIME_R) + if (gmtime_r(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); +#elif defined(HAVE_PGMTIME) + if (gmtime(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); +#elif defined(HAVE_GMTIME) + if ((pT = gmtime(&n))) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%SZ", pT); +#elif defined(HAVE_GETTIMEOFDAY) + struct timezone tz; + memset((void*)&tz, 0, sizeof(tz)); +# if defined(HAVE_LOCALTIME_R) + if (localtime_r(&n, pT)) + { struct timeval tv; + gettimeofday(&tv, &tz); + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60); + } +# else + if ((pT = localtime(&n))) + { struct timeval tv; + gettimeofday(&tv, &tz); + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -tz.tz_minuteswest/60+(pT->tm_isdst!=0), abs(tz.tz_minuteswest)%60); + } +#endif +#elif defined(HAVE_FTIME) + struct timeb t; + memset((void*)&t, 0, sizeof(t)); +# if defined(HAVE_LOCALTIME_R) + if (localtime_r(&n, pT)) + { +#ifdef __BORLANDC__ + ::ftime(&t); +#else + ftime(&t); +#endif + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60); + } + /* The following defines were added for VxWorks*/ +# elif defined(HAVE_PLOCALTIME_R) + if (localtime_r(&n, pT)) + { strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf+strlen(soap->tmpbuf), "%+03d:%02d", t.timezone/60, abs(t.timezone)%60); + } +# else + if ((pT = localtime(&n))) + { +#ifdef __BORLANDC__ + ::ftime(&t); +#else + ftime(&t); +#endif + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + sprintf(soap->tmpbuf + strlen(soap->tmpbuf), "%+03d:%02d", -t.timezone/60+(pT->tm_isdst!=0), abs(t.timezone)%60); + } +# endif +#elif defined(HAVE_LOCALTIME_R) + if (localtime_r(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); + /* The following defines were added for VxWorks*/ +#elif defined(HAVE_PLOCALTIME_R) + if (localtime_r(&n, pT)) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); +#else + if ((pT = localtime(&n))) + strftime(soap->tmpbuf, sizeof(soap->tmpbuf), "%Y-%m-%dT%H:%M:%S", pT); +#endif + else + strcpy(soap->tmpbuf, "1969-12-31T23:59:59Z"); + return soap->tmpbuf; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outdateTime(struct soap *soap, const char *tag, int id, const time_t *p, const char *type, int n) +{ if (soap_element_begin_out(soap, tag, soap_embedded_id(soap, id, p, n), type) + || soap_string_out(soap, soap_dateTime2s(soap, *p), 0)) + return soap->error; + return soap_element_end_out(soap, tag); +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_s2dateTime(struct soap *soap, const char *s, time_t *p) +{ if (s) + { struct tm T; + char zone[32]; + const char *t; + memset((void*)&T, 0, sizeof(T)); + zone[sizeof(zone)-1] = '\0'; + if (strchr(s, '-')) + t = "%d-%d-%dT%d:%d:%d%31s"; + else if (strchr(s, ':')) + t = "%4d%2d%2dT%d:%d:%d%31s"; + else /* parse non-XSD-standard alternative ISO 8601 format */ + t = "%4d%2d%2dT%2d%2d%2d%31s"; + sscanf(s, t, &T.tm_year, &T.tm_mon, &T.tm_mday, &T.tm_hour, &T.tm_min, &T.tm_sec, zone); + if (T.tm_year == 1) + T.tm_year = 70; + else + T.tm_year -= 1900; + T.tm_mon--; + if (*zone) + { if (*zone == '.') + { for (s = zone + 1; *s; s++) + if (*s < '0' || *s > '9') + break; + } + else + s = zone; + if (*s == '+' || *s == '-') + { int h = 0, m = 0; + if (s[3] == ':') + { sscanf(s, "%d:%d", &h, &m); + if (h < 0) + m = -m; + } + else + { m = (int)atol(s); + h = m / 100; + m = m % 100; + } + T.tm_hour -= h; + T.tm_min -= m; + } + T.tm_isdst = 0; + *p = soap_timegm(&T); + } + else + { T.tm_isdst = -1; + *p = mktime(&T); /* no time zone: suppose it is localtime? */ + } + } + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +time_t * +SOAP_FMAC2 +soap_indateTime(struct soap *soap, const char *tag, time_t *p, const char *type, int t) +{ if (soap_element_begin_in(soap, tag, 0, NULL)) + return NULL; + if (*soap->type + && soap_match_tag(soap, soap->type, type) + && soap_match_tag(soap, soap->type, ":dateTime")) + { soap->error = SOAP_TYPE; + soap_revert(soap); + return NULL; + } + p = (time_t*)soap_id_enter(soap, soap->id, p, t, sizeof(time_t), 0, NULL, NULL, NULL); + if (*soap->href) + p = (time_t*)soap_id_forward(soap, soap->href, p, 0, t, 0, sizeof(time_t), 0, NULL); + else if (p) + { if (soap_s2dateTime(soap, soap_value(soap), p)) + return NULL; + } + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outliteral(struct soap *soap, const char *tag, char *const*p, const char *type) +{ int i; + const char *t = NULL; + if (tag && *tag != '-') + { if (soap->local_namespaces && (t = strchr(tag, ':'))) + { strncpy(soap->tmpbuf, tag, t-tag); + soap->tmpbuf[t-tag] = '\0'; + for (i = 0; soap->local_namespaces[i].id; i++) + if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id)) + break; + t++; + if (soap_element(soap, t, 0, type) + || soap_attribute(soap, "xmlns", soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS) + || soap_element_start_end_out(soap, NULL)) + return soap->error; + } + else + { t = tag; + if (soap_element_begin_out(soap, t, 0, type)) + return soap->error; + } + } + if (p && *p) + { if (soap_send(soap, *p)) + return soap->error; + } + if (t) + return soap_element_end_out(soap, t); + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +char ** +SOAP_FMAC2 +soap_inliteral(struct soap *soap, const char *tag, char **p) +{ if (soap_element_begin_in(soap, tag, 1, NULL)) + { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT) + return NULL; + soap->error = SOAP_OK; + } + if (!p) + { if (!(p = (char**)soap_malloc(soap, sizeof(char*)))) + return NULL; + } + if (soap->body) + { *p = soap_string_in(soap, 0, -1, -1); + if (!*p) + return NULL; + if (!**p && tag && *tag == '-') + { soap->error = SOAP_NO_TAG; + return NULL; + } + } + else if (tag && *tag == '-') + { soap->error = SOAP_NO_TAG; + return NULL; + } + else if (soap->null) + *p = NULL; + else + *p = (char*)SOAP_STR_EOS; + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_outwliteral(struct soap *soap, const char *tag, wchar_t *const*p, const char *type) +{ int i; + const char *t = NULL; + if (tag && *tag != '-') + { if (soap->local_namespaces && (t = strchr(tag, ':'))) + { strncpy(soap->tmpbuf, tag, t-tag); + soap->tmpbuf[t-tag] = '\0'; + for (i = 0; soap->local_namespaces[i].id; i++) + if (!strcmp(soap->tmpbuf, soap->local_namespaces[i].id)) + break; + t++; + if (soap_element(soap, t, 0, type) + || soap_attribute(soap, "xmlns", soap->local_namespaces[i].ns ? soap->local_namespaces[i].ns : SOAP_STR_EOS) + || soap_element_start_end_out(soap, NULL)) + return soap->error; + } + else + { t = tag; + if (soap_element_begin_out(soap, t, 0, type)) + return soap->error; + } + if (soap_send(soap, soap->tmpbuf)) + return soap->error; + } + if (p) + { wchar_t c; + const wchar_t *s = *p; + while ((c = *s++)) + { if (soap_pututf8(soap, (unsigned long)c)) + return soap->error; + } + } + if (t) + return soap_element_end_out(soap, t); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_2 +SOAP_FMAC1 +wchar_t ** +SOAP_FMAC2 +soap_inwliteral(struct soap *soap, const char *tag, wchar_t **p) +{ if (soap_element_begin_in(soap, tag, 1, NULL)) + { if (soap->error != SOAP_NO_TAG || soap_unget(soap, soap_get(soap)) == SOAP_TT) + return NULL; + soap->error = SOAP_OK; + } + if (!p) + { if (!(p = (wchar_t**)soap_malloc(soap, sizeof(wchar_t*)))) + return NULL; + } + if (soap->body) + { *p = soap_wstring_in(soap, 0, -1, -1); + if (!*p) + return NULL; + if (!**p && tag && *tag == '-') + { soap->error = SOAP_NO_TAG; + return NULL; + } + } + else if (tag && *tag == '-') + { soap->error = SOAP_NO_TAG; + return NULL; + } + else if (soap->null) + *p = NULL; + else + *p = (wchar_t*)SOAP_STR_EOS; + if (soap->body && soap_element_end_in(soap, tag)) + return NULL; + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +const char * +SOAP_FMAC2 +soap_value(struct soap *soap) +{ register size_t i; + register soap_wchar c = 0; + register char *s = soap->tmpbuf; + if (!soap->body) + return SOAP_STR_EOS; + do c = soap_get(soap); + while (soap_blank(c)); + for (i = 0; i < sizeof(soap->tmpbuf) - 1; i++) + { if (c == SOAP_TT || (int)c == EOF) + break; + *s++ = (char)c; + c = soap_get(soap); + } + for (s--; i > 0; i--, s--) + { if (!soap_blank(*s)) + break; + } + s[1] = '\0'; + if ((int)c == EOF || c == SOAP_TT) + soap_unget(soap, c); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Element content value='%s'\n", soap->tmpbuf)); +#ifdef WITH_DOM + if ((soap->mode & SOAP_XML_DOM) && soap->dom) + soap->dom->data = soap_strdup(soap, soap->tmpbuf); +#endif + return soap->tmpbuf; /* return non-null pointer */ +} +#endif + +/******************************************************************************/ +#if !defined(WITH_LEANER) || !defined(WITH_NOHTTP) +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getline(struct soap *soap, char *s, int len) +{ int i = len; + soap_wchar c = 0; + for (;;) + { while (--i > 0) + { c = soap_getchar(soap); + if (c == '\r' || c == '\n') + break; + if ((int)c == EOF) + return soap->error = SOAP_EOF; + *s++ = (char)c; + } + if (c != '\n') + c = soap_getchar(soap); /* got \r or something else, now get \n */ + if (c == '\n') + { *s = '\0'; + if (i+1 == len) /* empty line: end of HTTP/MIME header */ + break; + c = soap_unget(soap, soap_getchar(soap)); + if (c != ' ' && c != '\t') /* HTTP line continuation? */ + break; + } + else if ((int)c == EOF) + return soap->error = SOAP_EOF; + } + if (i < 0) + return soap->error = SOAP_HDR; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static size_t +soap_count_attachments(struct soap *soap) +{ +#ifndef WITH_LEANER + register struct soap_multipart *content; + register size_t count = soap->count; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the message size with attachments, current count=%lu\n", (unsigned long)count)); + if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of DIME attachments\n")); + for (content = soap->dime.first; content; content = content->next) + { count += 12 + ((content->size+3)&(~3)); + if (content->id) + count += ((strlen(content->id)+3)&(~3)); + if (content->type) + count += ((strlen(content->type)+3)&(~3)); + if (content->options) + count += ((((unsigned char)content->options[2] << 8) | ((unsigned char)content->options[3]))+7)&(~3); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of DIME attachment content is %lu bytes\n", (unsigned long)content->size)); + } + } + if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary) + { register size_t n = strlen(soap->mime.boundary); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Calculating the size of MIME attachments\n")); + for (content = soap->mime.first; content; content = content->next) + { register const char *s; + /* count \r\n--boundary\r\n */ + count += 6 + n; + /* count Content-Type: ...\r\n */ + if (content->type) + count += 16 + strlen(content->type); + /* count Content-Transfer-Encoding: ...\r\n */ + s = soap_code_str(mime_codes, content->encoding); + if (s) + count += 29 + strlen(s); + /* count Content-ID: ...\r\n */ + if (content->id) + count += 14 + strlen(content->id); + /* count Content-Location: ...\r\n */ + if (content->location) + count += 20 + strlen(content->location); + /* count Content-Description: ...\r\n */ + if (content->description) + count += 23 + strlen(content->description); + /* count \r\n...content */ + count += 2 + content->size; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Size of MIME attachment content is %lu bytes\n", (unsigned long)content->size)); + } + /* count \r\n--boundary-- */ + count += 6 + n; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "New count is %lu bytes\n", (unsigned long)count)); + return count; +#else + return soap->count; +#endif +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static int +soap_putdimefield(struct soap *soap, const char *s, size_t n) +{ if (soap_send_raw(soap, s, n)) + return soap->error; + return soap_send_raw(soap, SOAP_STR_PADDING, -(long)n&3); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_dime_option(struct soap *soap, unsigned short optype, const char *option) +{ size_t n; + char *s = NULL; + if (option) + { n = strlen(option); + s = (char*)soap_malloc(soap, n + 5); + if (s) + { s[0] = (char)(optype >> 8); + s[1] = (char)(optype & 0xFF); + s[2] = (char)(n >> 8); + s[3] = (char)(n & 0xFF); + strcpy(s + 4, option); + } + } + return s; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putdimehdr(struct soap *soap) +{ unsigned char tmp[12]; + size_t optlen = 0, idlen = 0, typelen = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Put DIME header id='%s'\n", soap->dime.id?soap->dime.id:"")); + if (soap->dime.options) + optlen = (((unsigned char)soap->dime.options[2] << 8) | ((unsigned char)soap->dime.options[3])) + 4; + if (soap->dime.id) + { idlen = strlen(soap->dime.id); + if (idlen > 0x0000FFFF) + idlen = 0x0000FFFF; + } + if (soap->dime.type) + { typelen = strlen(soap->dime.type); + if (typelen > 0x0000FFFF) + typelen = 0x0000FFFF; + } + tmp[0] = SOAP_DIME_VERSION | (soap->dime.flags & 0x7); + tmp[1] = soap->dime.flags & 0xF0; + tmp[2] = (char)(optlen >> 8); + tmp[3] = (char)(optlen & 0xFF); + tmp[4] = (char)(idlen >> 8); + tmp[5] = (char)(idlen & 0xFF); + tmp[6] = (char)(typelen >> 8); + tmp[7] = (char)(typelen & 0xFF); + tmp[8] = (char)(soap->dime.size >> 24); + tmp[9] = (char)((soap->dime.size >> 16) & 0xFF); + tmp[10] = (char)((soap->dime.size >> 8) & 0xFF); + tmp[11] = (char)(soap->dime.size & 0xFF); + if (soap_send_raw(soap, (char*)tmp, 12) + || soap_putdimefield(soap, soap->dime.options, optlen) + || soap_putdimefield(soap, soap->dime.id, idlen) + || soap_putdimefield(soap, soap->dime.type, typelen)) + return soap->error; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putdime(struct soap *soap) +{ struct soap_multipart *content; + if (!(soap->mode & SOAP_ENC_DIME)) + return SOAP_OK; + for (content = soap->dime.first; content; content = content->next) + { void *handle; + soap->dime.size = content->size; + soap->dime.id = content->id; + soap->dime.type = content->type; + soap->dime.options = content->options; + soap->dime.flags = SOAP_DIME_VERSION | SOAP_DIME_MEDIA; + if (soap->fdimereadopen && ((handle = soap->fdimereadopen(soap, (void*)content->ptr, content->id, content->type, content->options)) || soap->error)) + { size_t size = content->size; + if (!handle) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadopen failed\n")); + return soap->error; + } + if (!size && ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE)) + { size_t chunksize = sizeof(soap->tmpbuf); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming DIME\n")); + do + { size = soap->fdimeread(soap, handle, soap->tmpbuf, chunksize); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread returned %lu bytes\n", (unsigned long)size)); + if (size < chunksize) + { soap->dime.flags &= ~SOAP_DIME_CF; + if (!content->next) + soap->dime.flags |= SOAP_DIME_ME; + } + else + soap->dime.flags |= SOAP_DIME_CF; + soap->dime.size = size; + if (soap_putdimehdr(soap) + || soap_putdimefield(soap, soap->tmpbuf, size)) + break; + if (soap->dime.id) + { soap->dime.flags &= ~(SOAP_DIME_MB | SOAP_DIME_MEDIA); + soap->dime.id = NULL; + soap->dime.type = NULL; + soap->dime.options = NULL; + } + } while (size >= chunksize); + } + else + { if (!content->next) + soap->dime.flags |= SOAP_DIME_ME; + if (soap_putdimehdr(soap)) + return soap->error; + do + { size_t bufsize; + if (size < sizeof(soap->tmpbuf)) + bufsize = size; + else + bufsize = sizeof(soap->tmpbuf); + if (!(bufsize = soap->fdimeread(soap, handle, soap->tmpbuf, bufsize))) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size)); + soap->error = SOAP_EOF; + break; + } + if (soap_send_raw(soap, soap->tmpbuf, bufsize)) + break; + size -= bufsize; + } while (size); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n")); + soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3); + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fdimereadclose\n")); + if (soap->fdimereadclose) + soap->fdimereadclose(soap, handle); + } + else + { if (!content->next) + soap->dime.flags |= SOAP_DIME_ME; + if (soap_putdimehdr(soap) + || soap_putdimefield(soap, (char*)content->ptr, content->size)) + return soap->error; + } + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static char * +soap_getdimefield(struct soap *soap, size_t n) +{ register soap_wchar c; + register size_t i; + register char *s; + register char *p = NULL; + if (n) + { p = (char*)soap_malloc(soap, n + 1); + if (p) + { s = p; + for (i = n; i > 0; i--) + { if ((int)(c = soap_get1(soap)) == EOF) + { soap->error = SOAP_EOF; + return NULL; + } + *s++ = (char)c; + } + *s = '\0'; + if ((soap->error = soap_move(soap, -(long)n&3))) + return NULL; + } + else + soap->error = SOAP_EOM; + } + return p; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getdimehdr(struct soap *soap) +{ register soap_wchar c; + register char *s; + register int i; + unsigned char tmp[12]; + size_t optlen, idlen, typelen; + if (!(soap->mode & SOAP_ENC_DIME)) + return soap->error = SOAP_DIME_END; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get DIME header\n")); + if (soap->dime.buflen || soap->dime.chunksize) + { if (soap_move(soap, (long)(soap->dime.size - soap_tell(soap)))) + return soap->error = SOAP_EOF; + soap_unget(soap, soap_getchar(soap)); /* skip padding and get hdr */ + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "... From chunked\n")); + return SOAP_OK; + } + s = (char*)tmp; + for (i = 12; i > 0; i--) + { if ((int)(c = soap_getchar(soap)) == EOF) + return soap->error = SOAP_EOF; + *s++ = (char)c; + } + if ((tmp[0] & 0xF8) != SOAP_DIME_VERSION) + return soap->error = SOAP_DIME_MISMATCH; + soap->dime.flags = (tmp[0] & 0x7) | (tmp[1] & 0xF0); + optlen = (tmp[2] << 8) | tmp[3]; + idlen = (tmp[4] << 8) | tmp[5]; + typelen = (tmp[6] << 8) | tmp[7]; + soap->dime.size = (tmp[8] << 24) | (tmp[9] << 16) | (tmp[10] << 8) | tmp[11]; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME size=%lu flags=0x%X\n", (unsigned long)soap->dime.size, soap->dime.flags)); + if (!(soap->dime.options = soap_getdimefield(soap, optlen)) && soap->error) + return soap->error; + if (!(soap->dime.id = soap_getdimefield(soap, idlen)) && soap->error) + return soap->error; + if (!(soap->dime.type = soap_getdimefield(soap, typelen)) && soap->error) + return soap->error; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "DIME id=%s, type=%s, options=%s\n", soap->dime.id?soap->dime.id:"", soap->dime.type?soap->dime.type:"", soap->dime.options?soap->dime.options+4:"")); + if (soap->dime.flags & SOAP_DIME_ME) + soap->mode &= ~SOAP_ENC_DIME; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getdime(struct soap *soap) +{ while (soap->dime.flags & SOAP_DIME_CF) + { if (soap_getdimehdr(soap)) + return soap->error; + if (soap_move(soap, (long)soap->dime.size)) + return soap->error = SOAP_EOF; + } + if (soap_move(soap, (long)(((soap->dime.size+3)&(~3))-soap_tell(soap)))) + return soap->error = SOAP_EOF; + for (;;) + { register struct soap_multipart *content; + if (soap_getdimehdr(soap)) + break; + if (soap->fdimewriteopen && ((soap->dime.ptr = (char*)soap->fdimewriteopen(soap, soap->dime.id, soap->dime.type, soap->dime.options)) || soap->error)) + { const char *id, *type, *options; + size_t size, n; + if (!soap->dime.ptr) + return soap->error; + id = soap->dime.id; + type = soap->dime.type; + options = soap->dime.options; + for (;;) + { size = soap->dime.size; + for (;;) + { n = soap->buflen - soap->bufidx; + if (size < n) + n = size; + if ((soap->error = soap->fdimewrite(soap, (void*)soap->dime.ptr, soap->buf + soap->bufidx, n))) + break; + size -= n; + if (!size) + { soap->bufidx += n; + break; + } + if (soap_recv(soap)) + { soap->error = SOAP_EOF; + goto end; + } + } + if (soap_move(soap, -(long)soap->dime.size&3)) + { soap->error = SOAP_EOF; + break; + } + if (!(soap->dime.flags & SOAP_DIME_CF)) + break; + if (soap_getdimehdr(soap)) + break; + } +end: + if (soap->fdimewriteclose) + soap->fdimewriteclose(soap, (void*)soap->dime.ptr); + soap->dime.size = 0; + soap->dime.id = id; + soap->dime.type = type; + soap->dime.options = options; + } + else if (soap->dime.flags & SOAP_DIME_CF) + { const char *id, *type, *options; + id = soap->dime.id; + type = soap->dime.type; + options = soap->dime.options; + if (soap_new_block(soap)) + return SOAP_EOM; + for (;;) + { register soap_wchar c; + register size_t i; + register char *s; + s = (char*)soap_push_block(soap, soap->dime.size); + if (!s) + return soap->error = SOAP_EOM; + for (i = soap->dime.size; i > 0; i--) + { if ((int)(c = soap_get1(soap)) == EOF) + return soap->error = SOAP_EOF; + *s++ = (char)c; + } + if (soap_move(soap, -(long)soap->dime.size&3)) + return soap->error = SOAP_EOF; + if (!(soap->dime.flags & SOAP_DIME_CF)) + break; + if (soap_getdimehdr(soap)) + return soap->error; + } + soap->dime.size = soap->blist->size++; /* allocate one more for '\0' */ + if (!(soap->dime.ptr = soap_save_block(soap, NULL, 0))) + return soap->error; + soap->dime.ptr[soap->dime.size] = '\0'; /* force 0-terminated */ + soap->dime.id = id; + soap->dime.type = type; + soap->dime.options = options; + } + else + soap->dime.ptr = soap_getdimefield(soap, soap->dime.size); + content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, soap->dime.ptr, soap->dime.size); + if (!content) + return soap->error = SOAP_EOM; + content->id = soap->dime.id; + content->type = soap->dime.type; + content->options = soap->dime.options; + if (soap->error) + return soap->error; + soap_resolve_attachment(soap, content); + } + if (soap->error != SOAP_DIME_END) + return soap->error; + return soap->error = SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getmimehdr(struct soap *soap) +{ struct soap_multipart *content; + do + { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) + return soap->error; + } + while (!*soap->msgbuf); + if (soap->msgbuf[0] == '-' && soap->msgbuf[1] == '-') + { char *s = soap->msgbuf + strlen(soap->msgbuf) - 1; + /* remove white space */ + while (soap_blank(*s)) + s--; + s[1] = '\0'; + if (soap->mime.boundary) + { if (strcmp(soap->msgbuf + 2, soap->mime.boundary)) + return soap->error = SOAP_MIME_ERROR; + } + else + soap->mime.boundary = soap_strdup(soap, soap->msgbuf + 2); + if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) + return soap->error; + } + if (soap_set_mime_attachment(soap, NULL, 0, SOAP_MIME_NONE, NULL, NULL, NULL, NULL)) + return soap->error = SOAP_EOM; + content = soap->mime.last; + for (;;) + { register char *key = soap->msgbuf; + register char *val; + if (!*key) + break; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "MIME header: %s\n", key)); + val = strchr(soap->msgbuf, ':'); + if (val) + { *val = '\0'; + do val++; + while (*val && *val <= 32); + if (!soap_tag_cmp(key, "Content-ID")) + content->id = soap_strdup(soap, val); + else if (!soap_tag_cmp(key, "Content-Location")) + content->location = soap_strdup(soap, val); + else if (!soap_tag_cmp(key, "Content-Disposition")) + content->id = soap_strdup(soap, soap_get_header_attribute(soap, val, "name")); + else if (!soap_tag_cmp(key, "Content-Type")) + content->type = soap_strdup(soap, val); + else if (!soap_tag_cmp(key, "Content-Description")) + content->description = soap_strdup(soap, val); + else if (!soap_tag_cmp(key, "Content-Transfer-Encoding")) + content->encoding = (enum soap_mime_encoding)soap_code_int(mime_codes, val, (long)SOAP_MIME_NONE); + } + if (soap_getline(soap, key, sizeof(soap->msgbuf))) + return soap->error; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getmime(struct soap *soap) +{ while (soap_get_mime_attachment(soap, NULL)) + ; + return soap->error; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_post_check_mime_attachments(struct soap *soap) +{ soap->imode |= SOAP_MIME_POSTCHECK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_check_mime_attachments(struct soap *soap) +{ if (soap->mode & SOAP_MIME_POSTCHECK) + return soap_get_mime_attachment(soap, NULL) != NULL; + return 0; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +struct soap_multipart * +SOAP_FMAC2 +soap_get_mime_attachment(struct soap *soap, void *handle) +{ register soap_wchar c = 0; + register size_t i, m = 0; + register char *s, *t = NULL; + register struct soap_multipart *content; + register short flag = 0; + if (!(soap->mode & SOAP_ENC_MIME)) + return NULL; + content = soap->mime.last; + if (!content) + { if (soap_getmimehdr(soap)) + return NULL; + content = soap->mime.last; + } + else if (content != soap->mime.first) + { if (soap->fmimewriteopen && ((content->ptr = (char*)soap->fmimewriteopen(soap, (void*)handle, content->id, content->type, content->description, content->encoding)) || soap->error)) + { if (!content->ptr) + return NULL; + } + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Parsing MIME content id=%s type=%s\n", content->id?content->id:"", content->type?content->type:"")); + if (!content->ptr && soap_new_block(soap)) + { soap->error = SOAP_EOM; + return NULL; + } + for (;;) + { if (content->ptr) + s = soap->tmpbuf; + else if (!(s = (char*)soap_push_block(soap, sizeof(soap->tmpbuf)))) + { soap->error = SOAP_EOM; + return NULL; + } + for (i = 0; i < sizeof(soap->tmpbuf); i++) + { if (m > 0) + { *s++ = *t++; + m--; + } + else + { if (!flag) + { c = soap_get1(soap); + if ((int)c == EOF) + { soap->error = SOAP_EOF; + return NULL; + } + } + if (flag || c == '\r') + { t = soap->msgbuf; + memset(t, 0, sizeof(soap->msgbuf)); + strcpy(t, "\n--"); + if (soap->mime.boundary) + strncat(t, soap->mime.boundary, sizeof(soap->msgbuf)-4); + do c = soap_getchar(soap); + while (c == *t++); + if ((int)c == EOF) + { soap->error = SOAP_EOF; + return NULL; + } + if (!*--t) + goto end; + *t = (char)c; + flag = (c == '\r'); + m = t - soap->msgbuf + 1 - flag; + t = soap->msgbuf; + c = '\r'; + } + *s++ = (char)c; + } + } + if (content->ptr && soap->fmimewrite) + { if ((soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i))) + break; + } + } +end: + *s = '\0'; /* force 0-terminated */ + if (content->ptr) + { if (!soap->error && soap->fmimewrite) + soap->error = soap->fmimewrite(soap, (void*)content->ptr, soap->tmpbuf, i); + if (soap->fmimewriteclose) + soap->fmimewriteclose(soap, (void*)content->ptr); + if (soap->error) + return NULL; + } + else + { content->size = soap_size_block(soap, i+1)-1; + content->ptr = soap_save_block(soap, NULL, 0); + } + soap_resolve_attachment(soap, content); + if (c == '-' && soap_getchar(soap) == '-') + { soap->mode &= ~SOAP_ENC_MIME; + if ((soap->mode & SOAP_MIME_POSTCHECK) && soap_end_recv(soap)) + return NULL; + } + else + { while (c != '\r' && (int)c != EOF && soap_blank(c)) + c = soap_getchar(soap); + if (c != '\r' || soap_getchar(soap) != '\n') + { soap->error = SOAP_MIME_ERROR; + return NULL; + } + if (soap_getmimehdr(soap)) + return NULL; + } + return content; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_match_cid(struct soap *soap, const char *s, const char *t) +{ register size_t n; + if (!s) + return 1; + if (!strcmp(s, t)) + return 0; + if (!strncmp(s, "cid:", 4)) + s += 4; + n = strlen(t); + if (*t == '<') + { t++; + n -= 2; + } + if (!strncmp(s, t, n) && !s[n]) + return 0; + soap_decode(soap->tmpbuf, sizeof(soap->tmpbuf), s, SOAP_STR_EOS); + if (!strncmp(soap->tmpbuf, t, n) && !soap->tmpbuf[n]) + return 0; + return 1; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static void +soap_resolve_attachment(struct soap *soap, struct soap_multipart *content) +{ if (content->id) + { register struct soap_xlist **xp = &soap->xlist; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Resolving attachment data for id=%s\n", content->id)); + while (*xp) + { register struct soap_xlist *xq = *xp; + if (!soap_match_cid(soap, xq->id, content->id)) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Found matching attachment %s for content id=%s\n", xq->id, content->id)); + *xp = xq->next; + *xq->ptr = (unsigned char*)content->ptr; + *xq->size = (int)content->size; + *xq->type = (char*)content->type; + if (content->options) + *xq->options = (char*)content->options; + else + *xq->options = (char*)content->description; + SOAP_FREE(soap, xq); + } + else + xp = &(*xp)->next; + } + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putmimehdr(struct soap *soap, struct soap_multipart *content) +{ const char *s; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "MIME attachment type=%s\n", content->type?content->type:"")); + if (soap_send3(soap, "\r\n--", soap->mime.boundary, "\r\n")) + return soap->error; + if (content->type && soap_send3(soap, "Content-Type: ", content->type, "\r\n")) + return soap->error; + s = soap_code_str(mime_codes, content->encoding); + if (s && soap_send3(soap, "Content-Transfer-Encoding: ", s, "\r\n")) + return soap->error; + if (content->id && soap_send3(soap, "Content-ID: ", content->id, "\r\n")) + return soap->error; + if (content->location && soap_send3(soap, "Content-Location: ", content->location, "\r\n")) + return soap->error; + if (content->description && soap_send3(soap, "Content-Description: ", content->description, "\r\n")) + return soap->error; + return soap_send_raw(soap, "\r\n", 2); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putmime(struct soap *soap) +{ struct soap_multipart *content; + if (!(soap->mode & SOAP_ENC_MIME) || !soap->mime.boundary) + return SOAP_OK; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending MIME attachments\n")); + for (content = soap->mime.first; content; content = content->next) + { void *handle; + if (soap->fmimereadopen && ((handle = soap->fmimereadopen(soap, (void*)content->ptr, content->id, content->type, content->description)) || soap->error)) + { size_t size = content->size; + if (!handle) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimereadopen failed\n")); + return soap->error; + } + if (soap_putmimehdr(soap, content)) + return soap->error; + if (!size) + { if ((soap->mode & SOAP_ENC_XML) || (soap->mode & SOAP_IO) == SOAP_IO_CHUNK || (soap->mode & SOAP_IO) == SOAP_IO_STORE) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked streaming MIME\n")); + do + { size = soap->fmimeread(soap, handle, soap->tmpbuf, sizeof(soap->tmpbuf)); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread returned %lu bytes\n", (unsigned long)size)); + if (soap_send_raw(soap, soap->tmpbuf, size)) + break; + } while (size); + } + else + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error: cannot chunk streaming MIME (no HTTP chunking)\n")); + } + } + else + { do + { size_t bufsize; + if (size < sizeof(soap->tmpbuf)) + bufsize = size; + else + bufsize = sizeof(soap->tmpbuf); + if (!(bufsize = soap->fmimeread(soap, handle, soap->tmpbuf, bufsize))) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "fmimeread failed: insufficient data (%lu bytes remaining from %lu bytes)\n", (unsigned long)size, (unsigned long)content->size)); + soap->error = SOAP_EOF; + break; + } + if (soap_send_raw(soap, soap->tmpbuf, bufsize)) + break; + size -= bufsize; + } while (size); + } + if (soap->fmimereadclose) + soap->fmimereadclose(soap, handle); + } + else + { if (soap_putmimehdr(soap, content) + || soap_send_raw(soap, content->ptr, content->size)) + return soap->error; + } + } + return soap_send3(soap, "\r\n--", soap->mime.boundary, "--"); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_dime(struct soap *soap) +{ soap->omode |= SOAP_ENC_DIME; + soap->dime.first = NULL; + soap->dime.last = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_mime(struct soap *soap, const char *boundary, const char *start) +{ soap->omode |= SOAP_ENC_MIME; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = soap_strdup(soap, boundary); + soap->mime.start = soap_strdup(soap, start); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_clr_dime(struct soap *soap) +{ soap->omode &= ~SOAP_ENC_DIME; + soap->dime.first = NULL; + soap->dime.last = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_clr_mime(struct soap *soap) +{ soap->omode &= ~SOAP_ENC_MIME; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = NULL; + soap->mime.start = NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static struct soap_multipart* +soap_new_multipart(struct soap *soap, struct soap_multipart **first, struct soap_multipart **last, char *ptr, size_t size) +{ struct soap_multipart *content; + content = (struct soap_multipart*)soap_malloc(soap, sizeof(struct soap_multipart)); + if (content) + { content->next = NULL; + content->ptr = ptr; + content->size = size; + content->id = NULL; + content->type = NULL; + content->options = NULL; + content->encoding = SOAP_MIME_NONE; + content->location = NULL; + content->description = NULL; + if (!*first) + *first = content; + if (*last) + (*last)->next = content; + *last = content; + } + return content; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_dime_attachment(struct soap *soap, char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option) +{ struct soap_multipart *content = soap_new_multipart(soap, &soap->dime.first, &soap->dime.last, ptr, size); + if (!content) + return SOAP_EOM; + content->id = soap_strdup(soap, id); + content->type = soap_strdup(soap, type); + content->options = soap_dime_option(soap, optype, option); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_mime_attachment(struct soap *soap, char *ptr, size_t size, enum soap_mime_encoding encoding, const char *type, const char *id, const char *location, const char *description) +{ struct soap_multipart *content = soap_new_multipart(soap, &soap->mime.first, &soap->mime.last, ptr, size); + if (!content) + return SOAP_EOM; + content->id = soap_strdup(soap, id); + content->type = soap_strdup(soap, type); + content->encoding = encoding; + content->location = soap_strdup(soap, location); + content->description = soap_strdup(soap, description); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +SOAP_FMAC1 +struct soap_multipart* +SOAP_FMAC2 +soap_next_multipart(struct soap_multipart *content) +{ if (content) + return content->next; + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static void +soap_select_mime_boundary(struct soap *soap) +{ while (!soap->mime.boundary || soap_valid_mime_boundary(soap)) + { register char *s = soap->mime.boundary; + register size_t n = 0; + if (s) + n = strlen(s); + if (n < 16) + { n = 64; + s = soap->mime.boundary = (char*)soap_malloc(soap, n + 1); + if (!s) + return; + } + strcpy(s, "=="); + s += 2; + n -= 4; + while (n) + { *s++ = soap_base64o[soap_random & 0x3F]; + n--; + } + strcpy(s, "=="); + } + if (!soap->mime.start) + soap->mime.start = ""; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEANER +#ifndef PALM_1 +static int +soap_valid_mime_boundary(struct soap *soap) +{ register struct soap_multipart *content; + register size_t k; + if (soap->fmimeread) + return SOAP_OK; + k = strlen(soap->mime.boundary); + for (content = soap->mime.first; content; content = content->next) + { if (content->ptr && content->size >= k) + { register const char *p = (const char*)content->ptr; + register size_t i; + for (i = 0; i < content->size - k; i++, p++) + { if (!strncmp(p, soap->mime.boundary, k)) + return SOAP_ERR; + } + } + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************\ + * + * HTTP cookie handling + * +\******************************************************************************/ + +#ifdef WITH_COOKIES +/******************************************************************************/ +SOAP_FMAC1 +size_t +SOAP_FMAC2 +soap_encode_cookie(const char *s, char *t, size_t len) +{ register int c; + register size_t n = len; + while ((c = *s++) && --n > 0) + { if (c > ' ' && c < 128 && !strchr("()<>@,;:\\\"/[]?={}", c)) + *t++ = c; + else if (n > 2) + { *t++ = '%'; + *t++ = (c >> 4) + (c > 159 ? '7' : '0'); + c &= 0xF; + *t++ = c + (c > 9 ? '7' : '0'); + n -= 2; + } + else + break; + } + *t = '\0'; + return len - n; +} + +/******************************************************************************/ +SOAP_FMAC1 +struct soap_cookie* +SOAP_FMAC2 +soap_cookie(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + size_t n; + if (!domain) + domain = soap->cookie_domain; + if (!path) + path = soap->cookie_path; + if (!path) + path = SOAP_STR_EOS; + else if (*path == '/') + path++; + n = strlen(path); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Search cookie %s domain=%s path=%s\n", name, domain?domain:"(null)", path?path:"(null)")); + for (p = soap->cookies; p; p = p->next) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie in database: %s=%s domain=%s path=%s env=%hd\n", p->name, p->value?p->value:"(null)", p->domain?p->domain:"(null)", p->path?p->path:"(null)", p->env)); + if (!strcmp(p->name, name) + && p->domain + && p->path + && !strcmp(p->domain, domain) + && !strncmp(p->path, path, n)) + break; + } + return p; +} + +/******************************************************************************/ +SOAP_FMAC1 +struct soap_cookie* +SOAP_FMAC2 +soap_set_cookie(struct soap *soap, const char *name, const char *value, const char *domain, const char *path) +{ struct soap_cookie **p, *q; + int n; + if (!domain) + domain = soap->cookie_domain; + if (!path) + path = soap->cookie_path; + if (!path) + path = SOAP_STR_EOS; + else if (*path == '/') + path++; + q = soap_cookie(soap, name, domain, path); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set %scookie: %s=%s domain=%s path=%s\n", q ? "" : "new ", name, value?value:"(null)", domain?domain:"(null)", path?path:"(null)")); + if (!q) + { if ((q = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie)))) + { if ((q->name = (char*)SOAP_MALLOC(soap, strlen(name)+1))) + strcpy(q->name, name); + q->value = NULL; + q->domain = NULL; + q->path = NULL; + q->expire = 0; + q->maxage = -1; + q->version = 1; + q->secure = 0; + q->modified = 0; + for (p = &soap->cookies, n = soap->cookie_max; *p && n; p = &(*p)->next, n--) + if (!strcmp((*p)->name, name) && (*p)->path && path && strcmp((*p)->path, path) < 0) + break; + if (n) + { q->next = *p; + *p = q; + } + else + { SOAP_FREE(soap, q->name); + SOAP_FREE(soap, q); + q = NULL; + } + } + } + else + q->modified = 1; + if (q) + { if (q->value) + { SOAP_FREE(soap, q->value); + q->value = NULL; + } + if (q->domain) + { SOAP_FREE(soap, q->domain); + q->domain = NULL; + } + if (q->path) + { SOAP_FREE(soap, q->path); + q->path = NULL; + } + if (value && *value && (q->value = (char*)SOAP_MALLOC(soap, strlen(value)+1))) + strcpy(q->value, value); + if (domain && (q->domain = (char*)SOAP_MALLOC(soap, strlen(domain)+1))) + strcpy(q->domain, domain); + if (path && (q->path = (char*)SOAP_MALLOC(soap, strlen(path)+1))) + strcpy(q->path, path); + q->session = 1; + q->env = 0; + } + return q; +} + +/******************************************************************************/ +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_clr_cookie(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie **p, *q; + if (!domain) + domain = soap->cookie_domain; + if (!domain) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error in clear cookie %s: cookie domain not set\n", name?name:"(null)")); + return; + } + if (!path) + path = soap->cookie_path; + if (!path) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error in clear cookie %s: cookie path not set\n", name?name:"(null)")); + return; + } + if (*path == '/') + path++; + for (p = &soap->cookies, q = *p; q; q = *p) + { if (!strcmp(q->name, name) && !strcmp(q->domain, domain) && !strncmp(q->path, path, strlen(q->path))) + { if (q->value) + SOAP_FREE(soap, q->value); + if (q->domain) + SOAP_FREE(soap, q->domain); + if (q->path) + SOAP_FREE(soap, q->path); + *p = q->next; + SOAP_FREE(soap, q); + } + else + p = &q->next; + } +} + +/******************************************************************************/ +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + return p->value; + return NULL; +} + +/******************************************************************************/ +SOAP_FMAC1 +char * +SOAP_FMAC2 +soap_env_cookie_value(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path)) && p->env) + return p->value; + return NULL; +} + +/******************************************************************************/ +SOAP_FMAC1 +time_t +SOAP_FMAC2 +soap_cookie_expire(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + return p->expire; + return -1; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_cookie_expire(struct soap *soap, const char *name, long expire, const char *domain, const char *path) +{ struct soap_cookie *p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set cookie expiration max-age %ld: %s domain=%s path=%s\n", expire, name, domain?domain:"(null)", path?path:"(null)")); + if ((p = soap_cookie(soap, name, domain, path))) + { p->maxage = expire; + p->modified = 1; + return SOAP_OK; + } + return SOAP_ERR; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + { p->session = 1; + p->modified = 1; + return SOAP_OK; + } + return SOAP_ERR; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_clr_cookie_session(struct soap *soap, const char *name, const char *domain, const char *path) +{ struct soap_cookie *p; + if ((p = soap_cookie(soap, name, domain, path))) + { p->session = 0; + p->modified = 1; + return SOAP_OK; + } + return SOAP_ERR; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putsetcookies(struct soap *soap) +{ struct soap_cookie *p; + char *s, tmp[4096]; + const char *t; + for (p = soap->cookies; p; p = p->next) + { + if (p->modified +#ifdef WITH_OPENSSL + || (!p->env && !soap->ssl == !p->secure) +#endif + ) + { s = tmp; + if (p->name) + s += soap_encode_cookie(p->name, s, tmp-s+4064); + if (p->value && *p->value) + { *s++ = '='; + s += soap_encode_cookie(p->value, s, tmp-s+4064); + } + if (p->domain && (int)strlen(p->domain) < tmp-s+4064) + { strcpy(s, ";Domain="); + strcat(s, p->domain); + } + else if (soap->cookie_domain && (int)strlen(soap->cookie_domain) < tmp-s+4064) + { strcpy(s, ";Domain="); + strcat(s, soap->cookie_domain); + } + strcat(s, ";Path=/"); + s += strlen(s); + if (p->path) + t = p->path; + else + t = soap->cookie_path; + if (t) + { if (*t == '/') + t++; + if ((int)strlen(t) < tmp-s+4064) + { if (strchr(t, '%')) /* already URL encoded? */ + { strcpy(s, t); + s += strlen(s); + } + else + s += soap_encode_cookie(t, s, tmp-s+4064); + } + } + if (p->version > 0 && s-tmp < 4060) + { sprintf(s, ";Version=%u", p->version); + s += strlen(s); + } + if (p->maxage >= 0 && s-tmp < 4060) + { sprintf(s, ";Max-Age=%ld", p->maxage); + s += strlen(s); + } + if (s-tmp < 4073 + && (p->secure +#ifdef WITH_OPENSSL + || soap->ssl +#endif + )) + strcpy(s, ";Secure"); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Set-Cookie: %s\n", tmp)); + if ((soap->error = soap->fposthdr(soap, "Set-Cookie", tmp))) + return soap->error; + } + } + return SOAP_OK; +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_putcookies(struct soap *soap, const char *domain, const char *path, int secure) +{ struct soap_cookie **p, *q; + unsigned int version = 0; + time_t now = time(NULL); + char *s, tmp[4096]; + p = &soap->cookies; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Sending cookies for domain=%s path=%s\n", domain, path)); + if (*path == '/') + path++; + while ((q = *p)) + { if (q->expire && now > q->expire) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie %s expired\n", q->name)); + SOAP_FREE(soap, q->name); + if (q->value) + SOAP_FREE(soap, q->value); + if (q->domain) + SOAP_FREE(soap, q->domain); + if (q->path) + SOAP_FREE(soap, q->path); + *p = q->next; + SOAP_FREE(soap, q); + } + else + { int flag; + char *t = q->domain; + size_t n = 0; + if (!t) + flag = 1; + else + { const char *r = strchr(t, ':'); + if (r) + n = r - t; + else + n = strlen(t); + flag = !strncmp(t, domain, n); + } + /* domain-level cookies */ + if (!flag) + { struct hostent *hostent = gethostbyname((char*)domain); + if (hostent) + { char *r = strchr(hostent->h_name, '.'); + if (!r) + r = hostent->h_name; + flag = !strncmp(t, r, n); + } + } + if (flag + && (!q->path || !strncmp(q->path, path, strlen(q->path))) + && (!q->secure || secure)) + { s = tmp; + if (q->version != version) + { sprintf(s, "$Version=%u;", q->version); + version = q->version; + } + if (q->name) + s += soap_encode_cookie(q->name, s, tmp-s+4080); + if (q->value && *q->value) + { *s++ = '='; + s += soap_encode_cookie(q->value, s, tmp-s+4080); + } + if (q->path && *q->path && (int)strlen(q->path) < tmp-s+4080) + { sprintf(s, ";$Path=\"/%s\"", (*q->path == '/' ? q->path + 1 : q->path)); + s += strlen(s); + } + if (q->domain && (int)strlen(q->domain) < tmp-s+4080) + sprintf(s, ";$Domain=\"%s\"", q->domain); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Cookie: %s\n", tmp)); + if ((soap->error = soap->fposthdr(soap, "Cookie", tmp))) + return soap->error; + } + p = &q->next; + } + } + return SOAP_OK; +} + +/******************************************************************************/ +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_getcookies(struct soap *soap, const char *val) +{ struct soap_cookie *p = NULL, *q; + const char *s; + char *t, tmp[4096]; /* cookie size is up to 4096 bytes [RFC2109] */ + char *domain = NULL; + char *path = NULL; + unsigned int version = 0; + time_t now = time(NULL); + if (!val) + return; + s = val; + while (*s) + { s = soap_decode_key(tmp, sizeof(tmp), s); + if (!soap_tag_cmp(tmp, "$Version")) + { if ((s = soap_decode_val(tmp, sizeof(tmp), s))) + { if (p) + p->version = (int)atol(tmp); + else + version = (int)atol(tmp); + } + } + else if (!soap_tag_cmp(tmp, "$Path")) + { s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) + strcpy(t, tmp); + } + else + t = NULL; + if (p) + { if (p->path) + SOAP_FREE(soap, p->path); + p->path = t; + } + else + { if (path) + SOAP_FREE(soap, path); + path = t; + } + } + else if (!soap_tag_cmp(tmp, "$Domain")) + { s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { if ((t = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) + strcpy(t, tmp); + } + else + t = NULL; + if (p) + { if (p->domain) + SOAP_FREE(soap, p->domain); + p->domain = t; + } + else + { if (domain) + SOAP_FREE(soap, domain); + domain = t; + } + } + else if (p && !soap_tag_cmp(tmp, "Path")) + { if (p->path) + SOAP_FREE(soap, p->path); + s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { if ((p->path = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) + strcpy(p->path, tmp); + } + else + p->path = NULL; + } + else if (p && !soap_tag_cmp(tmp, "Domain")) + { if (p->domain) + SOAP_FREE(soap, p->domain); + s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { if ((p->domain = (char*)SOAP_MALLOC(soap, strlen(tmp)+1))) + strcpy(p->domain, tmp); + } + else + p->domain = NULL; + } + else if (p && !soap_tag_cmp(tmp, "Version")) + { s = soap_decode_val(tmp, sizeof(tmp), s); + p->version = (unsigned int)atol(tmp); + } + else if (p && !soap_tag_cmp(tmp, "Max-Age")) + { s = soap_decode_val(tmp, sizeof(tmp), s); + p->expire = now + atol(tmp); + } + else if (p && !soap_tag_cmp(tmp, "Expires")) + { struct tm T; + char a[3]; + static const char mns[] = "anebarprayunulugepctovec"; + s = soap_decode_val(tmp, sizeof(tmp), s); + if (strlen(tmp) > 20) + { memset((void*)&T, 0, sizeof(T)); + a[0] = tmp[4]; + a[1] = tmp[5]; + a[2] = '\0'; + T.tm_mday = (int)atol(a); + a[0] = tmp[8]; + a[1] = tmp[9]; + T.tm_mon = (int)(strstr(mns, a) - mns) / 2; + a[0] = tmp[11]; + a[1] = tmp[12]; + T.tm_year = 100 + (int)atol(a); + a[0] = tmp[13]; + a[1] = tmp[14]; + T.tm_hour = (int)atol(a); + a[0] = tmp[16]; + a[1] = tmp[17]; + T.tm_min = (int)atol(a); + a[0] = tmp[19]; + a[1] = tmp[20]; + T.tm_sec = (int)atol(a); + p->expire = soap_timegm(&T); + } + } + else if (p && !soap_tag_cmp(tmp, "Secure")) + p->secure = 1; + else + { if (p) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie %s=%s domain=%s path=%s expire=%ld secure=%d\n", p->name, p->value?p->value:"(null)", p->domain?p->domain:"(null)", p->path?p->path:"(null)", p->expire, p->secure)); + if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path))) + { q->version = p->version; + q->expire = p->expire; + q->secure = p->secure; + q->env = 1; + } + if (p->name) + SOAP_FREE(soap, p->name); + if (p->value) + SOAP_FREE(soap, p->value); + if (p->domain) + SOAP_FREE(soap, p->domain); + if (p->path) + SOAP_FREE(soap, p->path); + SOAP_FREE(soap, p); + } + if ((p = (struct soap_cookie*)SOAP_MALLOC(soap, sizeof(struct soap_cookie)))) + { p->name = (char*)SOAP_MALLOC(soap, strlen(tmp)+1); + strcpy(p->name, tmp); + s = soap_decode_val(tmp, sizeof(tmp), s); + if (*tmp) + { p->value = (char*)SOAP_MALLOC(soap, strlen(tmp)+1); + strcpy(p->value, tmp); + } + else + p->value = NULL; + if (domain) + p->domain = domain; + else if (*soap->host) + { p->domain = (char*)SOAP_MALLOC(soap, strlen(soap->host)+1); + strcpy(p->domain, soap->host); + } + else + p->domain = NULL; + if (path) + p->path = path; + else if (soap->path && *soap->path) + { p->path = (char*)SOAP_MALLOC(soap, strlen(soap->path)+1); + strcpy(p->path, soap->path); + } + else + { p->path = (char*)SOAP_MALLOC(soap, 2); + strcpy(p->path, "/"); + } + p->expire = 0; + p->secure = 0; + p->version = version; + } + } + } + if (p) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Got environment cookie %s=%s domain=%s path=%s expire=%ld secure=%d\n", p->name, p->value?p->value:"(null)", p->domain?p->domain:"(null)", p->path?p->path:"(null)", p->expire, p->secure)); + if ((q = soap_set_cookie(soap, p->name, p->value, p->domain, p->path))) + { q->version = p->version; + q->expire = p->expire; + q->secure = p->secure; + q->env = 1; + } + if (p->name) + SOAP_FREE(soap, p->name); + if (p->value) + SOAP_FREE(soap, p->value); + if (p->domain) + SOAP_FREE(soap, p->domain); + if (p->path) + SOAP_FREE(soap, p->path); + SOAP_FREE(soap, p); + } + if (domain) + SOAP_FREE(soap, domain); + if (path) + SOAP_FREE(soap, path); +} + +/******************************************************************************/ +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_getenv_cookies(struct soap *soap) +{ struct soap_cookie *p; + const char *s; + char key[4096], val[4096]; /* cookie size is up to 4096 bytes [RFC2109] */ + if (!(s = getenv("HTTP_COOKIE"))) + return SOAP_ERR; + do + { s = soap_decode_key(key, sizeof(key), s); + s = soap_decode_val(val, sizeof(val), s); + p = soap_set_cookie(soap, key, val, NULL, NULL); + if (p) + p->env = 1; + } while (*s); + return SOAP_OK; +} + +/******************************************************************************/ +SOAP_FMAC1 +struct soap_cookie* +SOAP_FMAC2 +soap_copy_cookies(struct soap *copy, struct soap *soap) +{ struct soap_cookie *p, **q, *r; + q = &r; + for (p = soap->cookies; p; p = p->next) + { if (!(*q = (struct soap_cookie*)SOAP_MALLOC(copy, sizeof(struct soap_cookie)))) + return r; + **q = *p; + if (p->name) + { if (((*q)->name = (char*)SOAP_MALLOC(copy, strlen(p->name)+1))) + strcpy((*q)->name, p->name); + } + if (p->value) + { if (((*q)->value = (char*)SOAP_MALLOC(copy, strlen(p->value)+1))) + strcpy((*q)->value, p->value); + } + if (p->domain) + { if (((*q)->domain = (char*)SOAP_MALLOC(copy, strlen(p->domain)+1))) + strcpy((*q)->domain, p->domain); + } + if (p->path) + { if (((*q)->path = (char*)SOAP_MALLOC(copy, strlen(p->path)+1))) + strcpy((*q)->path, p->path); + } + q = &(*q)->next; + } + *q = NULL; + return r; +} + +/******************************************************************************/ +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_free_cookies(struct soap *soap) +{ struct soap_cookie *p; + for (p = soap->cookies; p; p = soap->cookies) + { soap->cookies = p->next; + SOAP_FREE(soap, p->name); + if (p->value) + SOAP_FREE(soap, p->value); + if (p->domain) + SOAP_FREE(soap, p->domain); + if (p->path) + SOAP_FREE(soap, p->path); + SOAP_FREE(soap, p); + } +} + +/******************************************************************************/ +#endif /* WITH_COOKIES */ + +/******************************************************************************/ +#ifdef WITH_GZIP +#ifndef PALM_1 +static int +soap_getgziphdr(struct soap *soap) +{ int i; + soap_wchar c = 0, f = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Get gzip header\n")); + for (i = 0; i < 9; i++) + { if ((int)(c = soap_get1(soap) == EOF)) + return soap->error = SOAP_EOF; + if (i == 2) + f = c; + } + if (f & 0x04) /* FEXTRA */ + { for (i = soap_get1(soap) | (soap_get1(soap) << 8); i; i--) + { if ((int)soap_get1(soap) == EOF) + return soap->error = SOAP_EOF; + } + } + if (f & 0x08) /* FNAME */ + { do + c = soap_get1(soap); + while (c && (int)c != EOF); + } + if ((int)c != EOF && (f & 0x10)) /* FCOMMENT */ + { do + c = soap_get1(soap); + while (c && (int)c != EOF); + } + if ((int)c != EOF && (f & 0x01)) /* FHCRC */ + { if ((int)(c = soap_get1(soap)) != EOF) + c = soap_get1(soap); + } + if ((int)c == EOF) + return soap->error = SOAP_EOF; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_begin_recv(struct soap *soap) +{ soap_wchar c; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Initializing for input\n")); + soap->error = SOAP_OK; + soap_free_temp(soap); + soap_set_local_namespaces(soap); + soap->version = 0; /* don't assume we're parsing SOAP content by default */ +#ifndef WITH_NOIDREF + soap_free_iht(soap); +#endif + if ((soap->imode & SOAP_IO) == SOAP_IO_CHUNK) + soap->omode |= SOAP_IO_CHUNK; + soap->imode &= ~SOAP_IO; + soap->mode = soap->imode; + if (!soap->keep_alive) + { soap->buflen = 0; + soap->bufidx = 0; + } + if (!(soap->mode & SOAP_IO_KEEPALIVE)) + soap->keep_alive = 0; + soap->ahead = 0; + soap->peeked = 0; + soap->level = 0; + soap->part = SOAP_BEGIN; + soap->alloced = 0; + soap->count = 0; + soap->length = 0; + soap->cdata = 0; + *soap->endpoint = '\0'; + soap->action = NULL; + soap->status = 0; +#ifndef WITH_LEANER + soap->dom = NULL; + soap->dime.chunksize = 0; + soap->dime.buflen = 0; + soap->dime.list = NULL; + soap->dime.first = NULL; + soap->dime.last = NULL; + soap->mime.list = NULL; + soap->mime.first = NULL; + soap->mime.last = NULL; + soap->mime.boundary = NULL; + soap->mime.start = NULL; + soap->xlist = NULL; +#endif +#ifdef WIN32 +#ifndef UNDER_CE +#ifndef WITH_FASTCGI + if (!soap_valid_socket(soap->socket)) +#ifdef __BORLANDC__ + setmode(soap->recvfd, O_BINARY); +#else + _setmode(soap->recvfd, _O_BINARY); +#endif +#endif +#endif +#endif +#ifdef WITH_ZLIB + soap->mode &= ~SOAP_ENC_ZLIB; + soap->zlib_in = SOAP_ZLIB_NONE; + soap->zlib_out = SOAP_ZLIB_NONE; + soap->d_stream.next_in = Z_NULL; + soap->d_stream.avail_in = 0; + soap->d_stream.next_out = (Byte*)soap->buf; + soap->d_stream.avail_out = SOAP_BUFLEN; + soap->z_ratio_in = 1.0; +#endif +#ifndef WITH_LEANER + if (soap->fprepareinit) + soap->fprepareinit(soap); +#endif + c = soap_getchar(soap); +#ifdef WITH_GZIP + if (c == 0x1F) + { if (soap_getgziphdr(soap)) + return soap->error; + if (inflateInit2(&soap->d_stream, -MAX_WBITS) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; + soap->zlib_state = SOAP_ZLIB_INFLATE; + soap->mode |= SOAP_ENC_ZLIB; + soap->zlib_in = SOAP_ZLIB_GZIP; + soap->z_crc = crc32(0L, NULL, 0); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n")); + memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); + /* should not chunk over plain transport, so why bother to check? */ + /* if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) */ + /* soap->z_buflen = soap->bufidx; */ + /* else */ + soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx); + soap->d_stream.avail_in = soap->buflen - soap->bufidx; + soap->z_buflen = soap->buflen; + soap->buflen = soap->bufidx; + c = soap_getchar(soap); + } +#endif +#ifndef WITH_LEANER + if (c == '-' && soap_get0(soap) == '-') + soap->mode |= SOAP_ENC_MIME; + else if ((c & 0xFFFC) == (SOAP_DIME_VERSION | SOAP_DIME_MB) && (soap_get0(soap) & 0xFFF0) == 0x20) + soap->mode |= SOAP_ENC_DIME; + else +#endif + { while (soap_blank(c)) + c = soap_getchar(soap); + } + if ((int)c == EOF) + return soap->error = SOAP_EOF; + soap_unget(soap, c); +#ifndef WITH_NOHTTP + /* if not XML or (start of)BOM or MIME/DIME/ZLIB, assume HTTP header */ + if (c != '<' && c != 0xEF && !(soap->mode & (SOAP_ENC_MIME | SOAP_ENC_DIME | SOAP_ENC_ZLIB))) + { soap->mode &= ~SOAP_IO; + soap->error = soap->fparse(soap); + if (soap->error && soap->error < SOAP_STOP) + { soap->keep_alive = 0; /* force close later */ + return soap->error; + } + if (soap->error == SOAP_STOP) + return soap->error; + if ((soap->mode & SOAP_IO) == SOAP_IO_CHUNK) + { soap->chunkbuflen = soap->buflen; + soap->buflen = soap->bufidx; + soap->chunksize = 0; + } +#ifndef WITH_LEANER + else if (soap->fpreparerecv && soap->buflen != soap->bufidx) + soap->fpreparerecv(soap, soap->buf + soap->bufidx, soap->buflen - soap->bufidx); +#endif + /* Note: fparse should not use soap_unget to push back last char */ + if (soap_get0(soap) == (int)EOF) + { if (soap->status == 200) + return soap->error = SOAP_NO_DATA; + return soap->error = soap->status; + } +#ifdef WITH_ZLIB + if (soap->zlib_in != SOAP_ZLIB_NONE) + { +#ifdef WITH_GZIP + if (soap->zlib_in != SOAP_ZLIB_DEFLATE) + { c = soap_get1(soap); + if (c == 0x1F) + { if (soap_getgziphdr(soap)) + return soap->error; + if (inflateInit2(&soap->d_stream, -MAX_WBITS) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; + soap->z_crc = crc32(0L, NULL, 0); + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "gzip initialized\n")); + } + else + { soap_revget1(soap); + if (inflateInit(&soap->d_stream) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; + soap->zlib_in = SOAP_ZLIB_DEFLATE; + } + } + else +#endif + if (inflateInit(&soap->d_stream) != Z_OK) + return soap->error = SOAP_ZLIB_ERROR; + soap->zlib_state = SOAP_ZLIB_INFLATE; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Inflate initialized\n")); + soap->mode |= SOAP_ENC_ZLIB; + memcpy(soap->z_buf, soap->buf, SOAP_BUFLEN); + soap->d_stream.next_in = (Byte*)(soap->z_buf + soap->bufidx); + soap->d_stream.avail_in = soap->buflen - soap->bufidx; + soap->z_buflen = soap->buflen; + soap->buflen = soap->bufidx; + } +#endif + if (soap->error) + { if (soap->error == SOAP_FORM && soap->fform) + { soap->error = soap->fform(soap); + if (soap->error == SOAP_OK) + soap->error = SOAP_STOP; /* prevents further processing */ + } + return soap->error; + } + } +#endif +#ifndef WITH_LEANER + if (soap->mode & SOAP_ENC_MIME) + { if (soap_getmimehdr(soap)) + return soap->error; + if (soap->mime.start) + { do + { if (!soap->mime.last->id) + break; + if (!soap_match_cid(soap, soap->mime.start, soap->mime.last->id)) + break; + } while (soap_get_mime_attachment(soap, NULL)); + } + if (soap_get_header_attribute(soap, soap->mime.first->type, "application/dime")) + soap->mode |= SOAP_ENC_DIME; + } + if (soap->mode & SOAP_ENC_DIME) + { if (soap_getdimehdr(soap)) + return soap->error; + if (soap->dime.flags & SOAP_DIME_CF) + { DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Chunked DIME SOAP message\n")); + soap->dime.chunksize = soap->dime.size; + if (soap->buflen - soap->bufidx >= soap->dime.chunksize) + { soap->dime.buflen = soap->buflen; + soap->buflen = soap->bufidx + soap->dime.chunksize; + } + else + soap->dime.chunksize -= soap->buflen - soap->bufidx; + } + soap->count = soap->buflen - soap->bufidx; + } +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_parse(struct soap *soap) +{ char header[SOAP_HDRLEN], *s; + unsigned short get = 0, status = 0, k = 0; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Waiting for HTTP request/response...\n")); + *soap->endpoint = '\0'; + soap->length = 0; + soap->userid = NULL; + soap->passwd = NULL; + soap->action = NULL; + soap->authrealm = NULL; + soap->proxy_from = NULL; + soap->http_content = NULL; + soap->status = 0; + do + { if (soap_getline(soap, soap->msgbuf, sizeof(soap->msgbuf))) + { if (soap->error == SOAP_EOF) + return SOAP_EOF; + return soap->error = 414; + } + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP status: %s\n", soap->msgbuf)); + for (;;) + { if (soap_getline(soap, header, SOAP_HDRLEN)) + { if (soap->error == SOAP_EOF) + { soap->error = SOAP_OK; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "EOF in HTTP header, continue anyway\n")); + break; + } + return soap->error; + } + if (!*header) + break; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP header: %s\n", header)); + s = strchr(header, ':'); + if (s) + { char *t; + *s = '\0'; + do s++; + while (*s && *s <= 32); + if (*s == '"') + s++; + t = s + strlen(s) - 1; + while (t > s && *t <= 32) + t--; + if (t >= s && *t == '"') + t--; + t[1] = '\0'; + if ((soap->error = soap->fparsehdr(soap, header, s))) + { if (soap->error < SOAP_STOP) + return soap->error; + status = soap->error; + soap->error = SOAP_OK; + } + } + } + if ((s = strchr(soap->msgbuf, ' '))) + { k = (unsigned short)soap_strtoul(s, &s, 10); + if (!soap_blank(*s)) + k = 0; + } + else + k = 0; + } while (k == 100); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Finished HTTP header parsing, status = %d\n", k)); + s = strstr(soap->msgbuf, "HTTP/"); + if (s && s[7] != '1') + { if (soap->keep_alive == 1) + soap->keep_alive = 0; + if (k == 0 && (soap->omode & SOAP_IO) == SOAP_IO_CHUNK) /* k == 0 for HTTP request */ + { soap->imode |= SOAP_IO_CHUNK; + soap->omode = (soap->omode & ~SOAP_IO) | SOAP_IO_STORE; + } + } + if (soap->keep_alive < 0) + soap->keep_alive = 1; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Keep alive connection = %d\n", soap->keep_alive)); + if (k == 0) + { if (s && (((get = !strncmp(soap->msgbuf, "GET ", 4))) || !strncmp(soap->msgbuf, "POST ", 5))) + { size_t m = strlen(soap->endpoint); + size_t n = m + (s - soap->msgbuf) - 5 - (!get); + if (m > n) + m = n; + if (n >= sizeof(soap->endpoint)) + n = sizeof(soap->endpoint) - 1; + strncpy(soap->path, soap->msgbuf + 4 + (!get), n - m); + soap->path[n - m] = '\0'; + strcat(soap->endpoint, soap->path); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Target endpoint='%s'\n", soap->endpoint)); + if (get) + { soap->error = soap->fget(soap); + if (soap->error == SOAP_OK) + soap->error = SOAP_STOP; /* prevents further processing */ + return soap->error; + } + if (status) + return soap->error = status; + } + else if (status) + return soap->error = status; + else if (s) + return soap->error = 405; + } + soap->status = k; + /* Status OK (HTTP 200) */ + if (k == 0 || k == 200) + return SOAP_OK; + /* Status 201 (Created), 202 (Accepted), ... and HTTP 400 and 500 errors. + Only keep parsing HTTP body when content-length>0 or chunked is set. + */ + if (((k > 200 && k <= 299) || k == 400 || k == 500) && (soap->length > 0 || (soap->imode & SOAP_IO) == SOAP_IO_CHUNK)) + return SOAP_OK; + /* HTTP 400 and 500 headers are supposed to set content-length or chunked. + For those that don't we keep parsing the body only if content type is + given and connection closes. + */ + if ((k == 400 || k == 500) && (soap->http_content || soap->keep_alive == 0)) + return SOAP_OK; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "HTTP error %d\n", k)); + return soap_set_receiver_error(soap, "HTTP Error", soap->msgbuf, k); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_parse_header(struct soap *soap, const char *key, const char *val) +{ if (!soap_tag_cmp(key, "Host")) + { +#ifdef WITH_OPENSSL + if (soap->imode & SOAP_ENC_SSL) + strcpy(soap->endpoint, "https://"); + else +#endif + strcpy(soap->endpoint, "http://"); + strncat(soap->endpoint, val, sizeof(soap->endpoint) - 8); + soap->endpoint[sizeof(soap->endpoint) - 1] = '\0'; + } +#ifndef WITH_LEANER + else if (!soap_tag_cmp(key, "Content-Type")) + { soap->http_content = soap_strdup(soap, val); + if (soap_get_header_attribute(soap, val, "application/dime")) + soap->mode |= SOAP_ENC_DIME; + else if (soap_get_header_attribute(soap, val, "multipart/related") + || soap_get_header_attribute(soap, val, "multipart/form-data")) + { soap->mime.boundary = soap_strdup(soap, soap_get_header_attribute(soap, val, "boundary")); + soap->mime.start = soap_strdup(soap, soap_get_header_attribute(soap, val, "start")); + soap->mode |= SOAP_ENC_MIME; + } + } +#endif + else if (!soap_tag_cmp(key, "Content-Length")) + { soap->length = soap_strtoul(val, NULL, 10); + } + else if (!soap_tag_cmp(key, "Content-Encoding")) + { if (!soap_tag_cmp(val, "deflate")) +#ifdef WITH_ZLIB + soap->zlib_in = SOAP_ZLIB_DEFLATE; +#else + return SOAP_ZLIB_ERROR; +#endif + else if (!soap_tag_cmp(val, "gzip")) +#ifdef WITH_GZIP + soap->zlib_in = SOAP_ZLIB_GZIP; +#else + return SOAP_ZLIB_ERROR; +#endif + } +#ifdef WITH_ZLIB + else if (!soap_tag_cmp(key, "Accept-Encoding")) + { +#ifdef WITH_GZIP + if (strchr(val, '*') || soap_get_header_attribute(soap, val, "gzip")) + soap->zlib_out = SOAP_ZLIB_GZIP; + else +#endif + if (strchr(val, '*') || soap_get_header_attribute(soap, val, "deflate")) + soap->zlib_out = SOAP_ZLIB_DEFLATE; + else + soap->zlib_out = SOAP_ZLIB_NONE; + } +#endif + else if (!soap_tag_cmp(key, "Transfer-Encoding")) + { soap->mode &= ~SOAP_IO; + if (!soap_tag_cmp(val, "chunked")) + soap->mode |= SOAP_IO_CHUNK; + } + else if (!soap_tag_cmp(key, "Connection")) + { if (!soap_tag_cmp(val, "keep-alive")) + soap->keep_alive = -soap->keep_alive; + else if (!soap_tag_cmp(val, "close")) + soap->keep_alive = 0; + } +#ifndef WITH_LEAN + else if (!soap_tag_cmp(key, "Authorization")) + { if (!soap_tag_cmp(val, "Basic *")) + { int n; + char *s; + soap_base642s(soap, val + 6, soap->tmpbuf, sizeof(soap->tmpbuf) - 1, &n); + soap->tmpbuf[n] = '\0'; + if ((s = strchr(soap->tmpbuf, ':'))) + { *s = '\0'; + soap->userid = soap_strdup(soap, soap->tmpbuf); + soap->passwd = soap_strdup(soap, s + 1); + } + } + } + else if (!soap_tag_cmp(key, "WWW-Authenticate")) + { soap->authrealm = soap_strdup(soap, soap_get_header_attribute(soap, val + 6, "realm")); + } + else if (!soap_tag_cmp(key, "Expect")) + { if (!soap_tag_cmp(val, "100-continue")) + { if ((soap->error = soap->fposthdr(soap, "HTTP/1.1 100 Continue", NULL)) + || (soap->error = soap->fposthdr(soap, NULL, NULL))) + return soap->error; + } + } +#endif + else if (!soap_tag_cmp(key, "SOAPAction")) + { if (*val == '"') + { soap->action = soap_strdup(soap, val + 1); + soap->action[strlen(soap->action) - 1] = '\0'; + } + else + soap->action = soap_strdup(soap, val); + } + else if (!soap_tag_cmp(key, "Location")) + { strncpy(soap->endpoint, val, sizeof(soap->endpoint)); + soap->endpoint[sizeof(soap->endpoint) - 1] = '\0'; + } + else if (!soap_tag_cmp(key, "X-Forwarded-For")) + { soap->proxy_from = soap_strdup(soap, val); + } +#ifdef WITH_COOKIES + else if (!soap_tag_cmp(key, "Cookie") + || !soap_tag_cmp(key, "Cookie2") + || !soap_tag_cmp(key, "Set-Cookie") + || !soap_tag_cmp(key, "Set-Cookie2")) + { soap_getcookies(soap, val); + } +#endif + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_get_header_attribute(struct soap *soap, const char *line, const char *key) +{ register const char *s = line; + if (s) + { while (*s) + { register short flag; + s = soap_decode_key(soap->tmpbuf, sizeof(soap->tmpbuf), s); + flag = soap_tag_cmp(soap->tmpbuf, key); + s = soap_decode_val(soap->tmpbuf, sizeof(soap->tmpbuf), s); + if (!flag) + return soap->tmpbuf; + } + } + return NULL; +} +#endif +#endif + +/******************************************************************************/ +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_decode_key(char *buf, size_t len, const char *val) +{ return soap_decode(buf, len, val, "=,;"); +} +#endif +#endif + +/******************************************************************************/ +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +#ifndef PALM_1 +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_decode_val(char *buf, size_t len, const char *val) +{ if (*val != '=') + { *buf = '\0'; + return val; + } + return soap_decode(buf, len, val + 1, ",;"); +} +#endif +#endif + +/******************************************************************************/ +#if !defined(WITH_NOHTTP) || !defined(WITH_LEANER) +#ifndef PALM_1 +static const char* +soap_decode(char *buf, size_t len, const char *val, const char *sep) +{ const char *s; + char *t = buf; + for (s = val; *s; s++) + if (*s != ' ' && *s != '\t' && !strchr(sep, *s)) + break; + if (*s == '"') + { s++; + while (*s && *s != '"' && --len) + *t++ = *s++; + } + else + { while (*s && !soap_blank(*s) && !strchr(sep, *s) && --len) + { if (*s == '%') + { *t++ = ((s[1] >= 'A' ? (s[1] & 0x7) + 9 : s[1] - '0') << 4) + + (s[2] >= 'A' ? (s[2] & 0x7) + 9 : s[2] - '0'); + s += 3; + } + else + *t++ = *s++; + } + } + *t = '\0'; + while (*s && !strchr(sep, *s)) + s++; + return s; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_envelope_begin_out(struct soap *soap) +{ +#ifndef WITH_LEANER + size_t n = 0; + if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && soap->mime.start && strlen(soap->mime.boundary) + strlen(soap->mime.start) < sizeof(soap->tmpbuf) - 80 ) + { const char *s; + if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) + s = "application/dime"; + else if (soap->version == 2) + { if (soap->mode & SOAP_ENC_MTOM) + s = "application/xop+xml; charset=utf-8; type=application/soap+xml"; + else + s = "application/soap+xml; charset=utf-8"; + } + else + s = "text/xml; charset=utf-8"; + sprintf(soap->tmpbuf, "--%s\r\nContent-Type: %s\r\nContent-Transfer-Encoding: binary\r\nContent-ID: %s\r\n\r\n", soap->mime.boundary, s, soap->mime.start); + n = strlen(soap->tmpbuf); + if (soap_send_raw(soap, soap->tmpbuf, n)) + return soap->error; + } + if (soap->mode & SOAP_IO_LENGTH) + soap->dime.size = soap->count; /* DIME in MIME correction */ + if (!(soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME)) + { if (soap_putdimehdr(soap)) + return soap->error; + } +#endif + soap->part = SOAP_IN_ENVELOPE; + return soap_element_begin_out(soap, "SOAP-ENV:Envelope", 0, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_envelope_end_out(struct soap *soap) +{ if (soap_element_end_out(soap, "SOAP-ENV:Envelope")) + return soap->error; +#ifndef WITH_LEANER + if ((soap->mode & SOAP_IO_LENGTH) && (soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) + { soap->dime.size = soap->count - soap->dime.size; /* DIME in MIME correction */ + sprintf(soap->id, soap->dime_id_format, 0); + soap->dime.id = soap->id; + if (soap->local_namespaces) + { if (soap->local_namespaces[0].out) + soap->dime.type = (char*)soap->local_namespaces[0].out; + else + soap->dime.type = (char*)soap->local_namespaces[0].ns; + } + soap->dime.options = NULL; + soap->dime.flags = SOAP_DIME_MB | SOAP_DIME_ABSURI; + if (!soap->dime.first) + soap->dime.flags |= SOAP_DIME_ME; + soap->count += 12 + ((strlen(soap->dime.id)+3)&(~3)) + (soap->dime.type ? ((strlen(soap->dime.type)+3)&(~3)) : 0); + } + if ((soap->mode & SOAP_ENC_DIME) && !(soap->mode & SOAP_ENC_MTOM)) + return soap_send_raw(soap, SOAP_STR_PADDING, -(long)soap->dime.size&3); +#endif + soap->part = SOAP_END_ENVELOPE; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_envelope_begin_in(struct soap *soap) +{ register struct Namespace *p; + soap->part = SOAP_IN_ENVELOPE; + if (soap_element_begin_in(soap, "SOAP-ENV:Envelope", 0, NULL)) + { +#ifndef WITH_LEAN + if (soap->error == SOAP_TAG_MISMATCH && !soap_element_begin_in(soap, "html", 0, NULL)) + { /* get HTML from buffer, stop receiving to avoid HTML parsing issues */ + char *s; +#ifndef WITH_NOIO + size_t (*f)(struct soap*, char*, size_t) = soap->frecv; + soap->frecv = frecv_stop; +#endif + soap_revert(soap); + s = soap_string_in(soap, 1, -1, -1); +#ifndef WITH_NOIO + soap->frecv = f; +#endif + return soap_set_receiver_error(soap, "HTTP Error", s, SOAP_HTTP_ERROR); + } +#endif + if (soap->error == SOAP_TAG_MISMATCH) + return soap->error = SOAP_VERSIONMISMATCH; + return soap->error; + } + p = soap->local_namespaces; + if (p) + { const char *ns = p[0].out; + if (!ns) + ns = p[0].ns; + if (!strcmp(ns, soap_env1)) + { soap->version = 1; /* make sure we use SOAP 1.1 */ + if (p[1].out) + SOAP_FREE(soap, p[1].out); + if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc1)))) + strcpy(p[1].out, soap_enc1); + } + else if (!strcmp(ns, soap_env2)) + { soap->version = 2; /* make sure we use SOAP 1.2 */ + if (p[1].out) + SOAP_FREE(soap, p[1].out); + if ((p[1].out = (char*)SOAP_MALLOC(soap, sizeof(soap_enc2)))) + strcpy(p[1].out, soap_enc2); + } + } + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_envelope_end_in(struct soap *soap) +{ soap->part = SOAP_END_ENVELOPE; + return soap_element_end_in(soap, "SOAP-ENV:Envelope"); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_body_begin_out(struct soap *soap) +{ soap->part = SOAP_IN_BODY; + if (soap->version == 1) + soap->encoding = 1; +#ifndef WITH_LEAN + if ((soap->mode & SOAP_XML_SEC) && soap_set_attr(soap, "wsu:Id", "Body")) + return soap->error; +#endif + if (soap_element(soap, "SOAP-ENV:Body", 0, NULL)) + return soap->error; + return soap_element_start_end_out(soap, NULL); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_body_end_out(struct soap *soap) +{ if (soap_element_end_out(soap, "SOAP-ENV:Body")) + return soap->error; + soap->part = SOAP_END_BODY; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_body_begin_in(struct soap *soap) +{ soap->part = SOAP_IN_BODY; + if (soap_element_begin_in(soap, "SOAP-ENV:Body", 0, NULL)) + return soap->error; + if (!soap->body) + soap->part = SOAP_NO_BODY; + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_body_end_in(struct soap *soap) +{ if (soap->part == SOAP_NO_BODY) + return SOAP_OK; + soap->part = SOAP_END_BODY; + return soap_element_end_in(soap, "SOAP-ENV:Body"); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv_header(struct soap *soap) +{ if (soap_getheader(soap) && soap->error == SOAP_TAG_MISMATCH) + soap->error = SOAP_OK; + else if (soap->error == SOAP_OK && soap->fheader) + soap->error = soap->fheader(soap); + return soap->error; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_endpoint(struct soap *soap, const char *endpoint) +{ register const char *s; + register size_t i, n; + soap->endpoint[0] = '\0'; + soap->host[0] = '\0'; + soap->path[0] = '/'; + soap->path[1] = '\0'; + soap->port = 80; + if (!endpoint || !*endpoint) + return; +#ifdef WITH_OPENSSL + if (!soap_tag_cmp(endpoint, "https:*")) + soap->port = 443; +#endif + strncpy(soap->endpoint, endpoint, sizeof(soap->endpoint) - 1); + soap->endpoint[sizeof(soap->endpoint) - 1] = '\0'; + s = strchr(endpoint, ':'); + if (s && s[1] == '/' && s[2] == '/') + s += 3; + else + s = endpoint; + n = strlen(s); + if (n >= sizeof(soap->host)) + n = sizeof(soap->host) - 1; +#ifdef WITH_IPV6 + if (s[0] == '[') + { s++; + for (i = 0; i < n; i++) + { if (s[i] == ']') + { s++; + --n; + break; + } + soap->host[i] = s[i]; + } + } + else + { for (i = 0; i < n; i++) + { soap->host[i] = s[i]; + if (s[i] == '/' || s[i] == ':') + break; + } + } +#else + for (i = 0; i < n; i++) + { soap->host[i] = s[i]; + if (s[i] == '/' || s[i] == ':') + break; + } +#endif + soap->host[i] = '\0'; + if (s[i] == ':') + { soap->port = (int)atol(s + i + 1); + for (i++; i < n; i++) + if (s[i] == '/') + break; + } + if (i < n && s[i]) + { strncpy(soap->path, s + i, sizeof(soap->path)); + soap->path[sizeof(soap->path) - 1] = '\0'; + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_connect(struct soap *soap, const char *endpoint, const char *action) +{ return soap_connect_command(soap, SOAP_POST, endpoint, action); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_connect_command(struct soap *soap, int http_command, const char *endpoint, const char *action) +{ char host[sizeof(soap->host)]; + int port; + size_t count; + soap->error = SOAP_OK; + strcpy(host, soap->host); /* save to compare */ + port = soap->port; /* save to compare */ + soap_set_endpoint(soap, endpoint); +#ifndef WITH_LEANER + if (soap->fconnect) + { if ((soap->error = soap->fconnect(soap, endpoint, soap->host, soap->port))) + return soap->error; + } + else +#endif + if (soap->fopen && *soap->host) + { soap->status = http_command; + if (!soap->keep_alive || !soap_valid_socket(soap->socket) || strcmp(soap->host, host) || soap->port != port || !soap->fpoll || soap->fpoll(soap)) + { soap->keep_alive = 0; /* to force close */ + soap->omode &= ~SOAP_IO_UDP; /* to force close */ + soap_closesock(soap); + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Connect/reconnect to host='%s' path='%s' port=%d\n", soap->host, soap->path, soap->port)); +#ifdef WITH_UDP + if (!strncmp(endpoint, "soap.udp:", 9)) + soap->omode |= SOAP_IO_UDP; +#endif + soap->socket = soap->fopen(soap, endpoint, soap->host, soap->port); + if (soap->error) + return soap->error; + soap->keep_alive = ((soap->omode & SOAP_IO_KEEPALIVE) != 0); + } + } + count = soap_count_attachments(soap); + if (soap_begin_send(soap)) + return soap->error; + if (http_command != SOAP_POST) + { soap->mode &= ~SOAP_IO; + soap->mode |= SOAP_IO_BUFFER; + } +#ifndef WITH_NOHTTP + soap->action = soap_strdup(soap, action); + if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML) && endpoint) + { unsigned int k = soap->mode; + soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB); + if ((k & SOAP_IO) != SOAP_IO_FLUSH) + soap->mode |= SOAP_IO_BUFFER; + if ((soap->error = soap->fpost(soap, endpoint, soap->host, soap->port, soap->path, action, count))) + return soap->error; +#ifndef WITH_LEANER + if ((k & SOAP_IO) == SOAP_IO_CHUNK) + { if (soap_flush(soap)) + return soap->error; + } +#endif + soap->mode = k; + } + if (http_command != SOAP_POST) + return soap_end_send(soap); +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_s2base64(struct soap *soap, const unsigned char *s, char *t, int n) +{ register int i; + register unsigned long m; + register char *p; + if (!t) + t = (char*)soap_malloc(soap, (n + 2) / 3 * 4 + 1); + if (!t) + { soap->error = SOAP_EOM; + return NULL; + } + p = t; + t[0] = '\0'; + if (!s) + return p; + for (; n > 2; n -= 3, s += 3) + { m = s[0]; + m = (m << 8) | s[1]; + m = (m << 8) | s[2]; + for (i = 4; i > 0; m >>= 6) + t[--i] = soap_base64o[m & 0x3F]; + t += 4; + } + t[0] = '\0'; + if (n > 0) + { m = 0; + for (i = 0; i < n; i++) + m = (m << 8) | *s++; + for (; i < 3; i++) + m <<= 8; + for (i++; i > 0; m >>= 6) + t[--i] = soap_base64o[m & 0x3F]; + for (i = 3; i > n; i--) + t[i] = '='; + t[4] = '\0'; + } + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_base642s(struct soap *soap, const char *s, char *t, size_t l, int *n) +{ register int i, j, c; + register unsigned long m; + register const char *p; + if (!s || !*s) + { if (n) + *n = 0; + if (soap->error) + return NULL; + return SOAP_NON_NULL; + } + if (!t) + { l = (strlen(s) + 3) / 4 * 3; + t = (char*)soap_malloc(soap, l); + } + if (!t) + { soap->error = SOAP_EOM; + return NULL; + } + p = t; + if (n) + *n = 0; + for (;;) + { for (i = 0; i < SOAP_BLKLEN; i++) + { m = 0; + j = 0; + while (j < 4) + { c = *s++; + if (c == '=' || !c) + { i *= 3; + switch (j) + { case 2: + *t++ = (char)((m >> 4) & 0xFF); + i++; + break; + case 3: + *t++ = (char)((m >> 10) & 0xFF); + *t++ = (char)((m >> 2) & 0xFF); + i += 2; + } + if (n) + *n += i; + return p; + } + c -= '+'; + if (c >= 0 && c <= 79) + { int b = soap_base64i[c]; + if (b >= 64) + { soap->error = SOAP_TYPE; + return NULL; + } + m = (m << 6) + b; + j++; + } + else if (!soap_blank(c + '+')) + { soap->error = SOAP_TYPE; + return NULL; + } + } + *t++ = (char)((m >> 16) & 0xFF); + *t++ = (char)((m >> 8) & 0xFF); + *t++ = (char)(m & 0xFF); + if (l < 3) + { if (n) + *n += i; + return p; + } + l -= 3; + } + if (n) + *n += 3 * SOAP_BLKLEN; + } +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_s2hex(struct soap *soap, const unsigned char *s, char *t, int n) +{ register char *p; + if (!t) + t = (char*)soap_malloc(soap, 2 * n + 1); + if (!t) + { soap->error = SOAP_EOM; + return NULL; + } + p = t; + t[0] = '\0'; + if (s) + { for (; n > 0; n--) + { register int m = *s++; + *t++ = (char)((m >> 4) + (m > 159 ? 'a' - 10 : '0')); + m &= 0x0F; + *t++ = (char)(m + (m > 9 ? 'a' - 10 : '0')); + } + } + *t++ = '\0'; + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +SOAP_FMAC1 +const char* +SOAP_FMAC2 +soap_hex2s(struct soap *soap, const char *s, char *t, size_t l, int *n) +{ register const char *p; + if (!s || !*s) + { if (n) + *n = 0; + if (soap->error) + return NULL; + return SOAP_NON_NULL; + } + if (!t) + { l = strlen(s) / 2; + t = (char*)soap_malloc(soap, l); + } + if (!t) + { soap->error = SOAP_EOM; + return NULL; + } + p = t; + while (l) + { register int d1, d2; + d1 = *s++; + if (!d1) + break; + d2 = *s++; + if (!d2) + break; + *t++ = ((d1 >= 'A' ? (d1 & 0x7) + 9 : d1 - '0') << 4) + (d2 >= 'A' ? (d2 & 0x7) + 9 : d2 - '0'); + l--; + } + if (n) + *n = (int)(t - p); + return p; +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_puthttphdr(struct soap *soap, int status, size_t count) +{ if (soap->status != SOAP_GET) + { register const char *s = "text/xml; charset=utf-8"; + register int err = SOAP_OK; +#ifndef WITH_LEANER + register const char *r = NULL; +#endif + if (status == SOAP_FILE && soap->http_content) + s = soap->http_content; + else if (status == SOAP_HTML) + s = "text/html; charset=utf-8"; + else if (count || ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK)) + { if (soap->version == 2) + s = "application/soap+xml; charset=utf-8"; + } +#ifndef WITH_LEANER + if (soap->mode & (SOAP_ENC_DIME | SOAP_ENC_MTOM)) + { if (soap->mode & SOAP_ENC_MTOM) + { r = s; + s = "application/xop+xml; charset=utf-8"; + } + else + s = "application/dime"; + } + if ((soap->mode & SOAP_ENC_MIME) && soap->mime.boundary && strlen(soap->mime.boundary) + strlen(soap->mime.start ? soap->mime.start : SOAP_STR_EOS) < sizeof(soap->tmpbuf) - 80) + { register const char *t = strchr(s, ';'); + sprintf(soap->tmpbuf, "multipart/related; boundary=\"%s\"; type=\"", soap->mime.boundary); + if (t) + strncat(soap->tmpbuf, s, t - s); + else + strcat(soap->tmpbuf, s); + if (soap->mime.start) + { strcat(soap->tmpbuf, "\"; start=\""); + strcat(soap->tmpbuf, soap->mime.start); + } + strcat(soap->tmpbuf, "\""); + if (r) + { strcat(soap->tmpbuf, "; start-info=\""); + strcat(soap->tmpbuf, r); + strcat(soap->tmpbuf, "\""); + } + s = soap->tmpbuf; + } +#endif + if (s && (err = soap->fposthdr(soap, "Content-Type", s))) + return err; +#ifdef WITH_ZLIB + if (soap->omode & SOAP_ENC_ZLIB) + { +#ifdef WITH_GZIP + err = soap->fposthdr(soap, "Content-Encoding", soap->zlib_out == SOAP_ZLIB_DEFLATE ? "deflate" : "gzip"); +#else + err = soap->fposthdr(soap, "Content-Encoding", "deflate"); +#endif + if (err) + return err; + } +#endif +#ifndef WITH_LEANER + if ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK) + err = soap->fposthdr(soap, "Transfer-Encoding", "chunked"); + else +#endif + if (s) + { sprintf(soap->tmpbuf, "%lu", (unsigned long)count); + err = soap->fposthdr(soap, "Content-Length", soap->tmpbuf); + } + if (err) + return err; + } + return soap->fposthdr(soap, "Connection", soap->keep_alive ? "keep-alive" : "close"); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_get(struct soap *soap) +{ return SOAP_GET_METHOD; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_post(struct soap *soap, const char *endpoint, const char *host, int port, const char *path, const char *action, size_t count) +{ register const char *s; + register int err; + if (soap->status == SOAP_GET) + s = "GET"; + else + s = "POST"; +#ifdef PALM + if (!endpoint || (soap_tag_cmp(endpoint, "http:*") && soap_tag_cmp(endpoint, "https:*") && strncmp(endpoint, "httpg:", 6)) && strncmp(endpoint, "_beam:", 6) && strncmp(endpoint, "_local:", 7) && strncmp(endpoint, "_btobex:", 8)) +#else + if (!endpoint || (soap_tag_cmp(endpoint, "http:*") && soap_tag_cmp(endpoint, "https:*") && strncmp(endpoint, "httpg:", 6))) +#endif + return SOAP_OK; + if (strlen(endpoint) + strlen(soap->http_version) > sizeof(soap->tmpbuf) - 80) + return soap->error = SOAP_EOM; + if (soap->proxy_host && soap_tag_cmp(endpoint, "https:*")) + sprintf(soap->tmpbuf, "%s %s HTTP/%s", s, endpoint, soap->http_version); + else + sprintf(soap->tmpbuf, "%s /%s HTTP/%s", s, (*path == '/' ? path + 1 : path), soap->http_version); + if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return err; +#ifdef WITH_OPENSSL + if ((soap->ssl && soap->port != 443) || (!soap->ssl && soap->port != 80)) + sprintf(soap->tmpbuf, "%s:%d", host, port); + else + strcpy(soap->tmpbuf, host); +#else + if (port != 80) + sprintf(soap->tmpbuf, "%s:%d", host, port); + else + strcpy(soap->tmpbuf, host); +#endif + if ((err = soap->fposthdr(soap, "Host", soap->tmpbuf)) + || (err = soap->fposthdr(soap, "User-Agent", "gSOAP/2.7")) + || (err = soap_puthttphdr(soap, SOAP_OK, count))) + return err; +#ifdef WITH_ZLIB +#ifdef WITH_GZIP + if ((err = soap->fposthdr(soap, "Accept-Encoding", "gzip, deflate"))) +#else + if ((err = soap->fposthdr(soap, "Accept-Encoding", "deflate"))) +#endif + return err; +#endif +#ifndef WITH_LEAN + if (soap->userid && soap->passwd && strlen(soap->userid) + strlen(soap->passwd) < 761) + { sprintf(soap->tmpbuf + 262, "%s:%s", soap->userid, soap->passwd); + strcpy(soap->tmpbuf, "Basic "); + soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262)); + if ((err = soap->fposthdr(soap, "Authorization", soap->tmpbuf))) + return err; + } + if (soap->proxy_userid && soap->proxy_passwd && strlen(soap->proxy_userid) + strlen(soap->proxy_passwd) < 761) + { sprintf(soap->tmpbuf + 262, "%s:%s", soap->proxy_userid, soap->proxy_passwd); + strcpy(soap->tmpbuf, "Basic "); + soap_s2base64(soap, (const unsigned char*)(soap->tmpbuf + 262), soap->tmpbuf + 6, (int)strlen(soap->tmpbuf + 262)); + if ((err = soap->fposthdr(soap, "Proxy-Authorization", soap->tmpbuf))) + return err; + } +#endif +#ifdef WITH_COOKIES +#ifdef WITH_OPENSSL + if (soap_putcookies(soap, host, path, soap->ssl != NULL)) + return soap->error; +#else + if (soap_putcookies(soap, host, path, 0)) + return soap->error; +#endif +#endif + if (soap->status != SOAP_GET && (soap->version == 1 || (action && *action && strlen(action) < sizeof(soap->tmpbuf) - 2))) + { sprintf(soap->tmpbuf, "\"%s\"", action?action:""); + if ((err = soap->fposthdr(soap, "SOAPAction", soap->tmpbuf))) + return err; + } + return soap->fposthdr(soap, NULL, NULL); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_send_header(struct soap *soap, const char *s) +{ register const char *t; + do + { t = strchr(s, '\n'); /* disallow \n in HTTP headers */ + if (!t) + t = s + strlen(s); + if (soap_send_raw(soap, s, t - s)) + return soap->error; + s = t + 1; + } while (*t); + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_post_header(struct soap *soap, const char *key, const char *val) +{ if (key) + { if (http_send_header(soap, key)) + return soap->error; + if (val && (soap_send_raw(soap, ": ", 2) || http_send_header(soap, val))) + return soap->error; + } + return soap_send_raw(soap, "\r\n", 2); +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +static int +http_response(struct soap *soap, int status, size_t count) +{ register int err; +#ifdef WMW_RPM_IO + if (soap->rpmreqid) + httpOutputEnable(soap->rpmreqid); +#endif + if (strlen(soap->http_version) > 4) + return soap->error = SOAP_EOM; + if (!status || status == SOAP_HTML || status == SOAP_FILE) + { const char *s; + if (count || ((soap->omode & SOAP_IO) == SOAP_IO_CHUNK)) + s = "200 OK"; + else + s = "202 ACCEPTED"; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Status = %s\n", s)); +#ifdef WMW_RPM_IO + if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */ +#else + if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application */ +#endif + { sprintf(soap->tmpbuf, "HTTP/%s %s", soap->http_version, s); + if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return err; + } + else if ((err = soap->fposthdr(soap, "Status", s))) + return err; + } + else if (status >= 200 && status < 600) + { sprintf(soap->tmpbuf, "HTTP/%s %d %s", soap->http_version, status, http_error(soap, status)); + if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return err; +#ifndef WITH_LEAN + if (status == 401) + { sprintf(soap->tmpbuf, "Basic realm=\"%s\"", (soap->authrealm ? strlen(soap->authrealm) : 18) < sizeof(soap->tmpbuf) - 14 ? soap->authrealm : "gSOAP Web Service"); + if ((err = soap->fposthdr(soap, "WWW-Authenticate", soap->tmpbuf))) + return err; + } + else if ((status >= 301 && status <= 303) || status == 307) + { if ((err = soap->fposthdr(soap, "Location", soap->endpoint))) + return err; + } +#endif + } + else + { const char *s = *soap_faultcode(soap); + if (soap->version == 2 && (!s || !strcmp(s, "SOAP-ENV:Sender"))) + s = "400 Bad Request"; + else + s = "500 Internal Server Error"; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Error %s (status=%d)\n", s, status)); +#ifdef WMW_RPM_IO + if (soap->rpmreqid || soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* RPM behaves as if standalone */ +#else + if (soap_valid_socket(soap->master) || soap_valid_socket(soap->socket)) /* standalone application */ +#endif + { sprintf(soap->tmpbuf, "HTTP/%s %s", soap->http_version, s); + if ((err = soap->fposthdr(soap, soap->tmpbuf, NULL))) + return err; + } + else if ((err = soap->fposthdr(soap, "Status", s))) /* CGI */ + return err; + } + if ((err = soap->fposthdr(soap, "Server", "gSOAP/2.7")) + || (err = soap_puthttphdr(soap, status, count))) + return err; +#ifdef WITH_COOKIES + if (soap_putsetcookies(soap)) + return soap->error; +#endif + return soap->fposthdr(soap, NULL, NULL); +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_response(struct soap *soap, int status) +{ register size_t count; + if (!(soap->omode & (SOAP_ENC_XML | SOAP_IO_STORE /* this tests for chunking too */)) + && (status == SOAP_HTML || status == SOAP_FILE)) + { soap->omode &= ~SOAP_IO; + soap->omode |= SOAP_IO_STORE; + } + soap->status = status; + count = soap_count_attachments(soap); + if (soap_begin_send(soap)) + return soap->error; +#ifndef WITH_NOHTTP + if ((soap->mode & SOAP_IO) != SOAP_IO_STORE && !(soap->mode & SOAP_ENC_XML)) + { register int n = soap->mode; + soap->mode &= ~(SOAP_IO | SOAP_ENC_ZLIB); + if ((n & SOAP_IO) != SOAP_IO_FLUSH) + soap->mode |= SOAP_IO_BUFFER; + if ((soap->error = soap->fresponse(soap, status, count))) + return soap->error; +#ifndef WITH_LEANER + if ((n & SOAP_IO) == SOAP_IO_CHUNK) + { if (soap_flush(soap)) + return soap->error; + } +#endif + soap->mode = n; + } +#endif + return SOAP_OK; +} +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +static const char* +soap_set_validation_fault(struct soap *soap, const char *s, const char *t) +{ if (*soap->tag) + sprintf(soap->msgbuf, "Validation constraint violation: %s%s in element <%s>", s, t?t:SOAP_STR_EOS, soap->tag); + else + sprintf(soap->msgbuf, "Validation constraint violation: %s%s", s, t?t:SOAP_STR_EOS); + return soap->msgbuf; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_set_fault(struct soap *soap) +{ const char **c = soap_faultcode(soap); + const char **s = soap_faultstring(soap); + if (soap->fseterror) + soap->fseterror(soap, c, s); + if (!*c) + { if (soap->version == 2) + *c = "SOAP-ENV:Sender"; + else + *c = "SOAP-ENV:Client"; + } + if (*s) + return; + switch (soap->error) + { +#ifndef WITH_LEAN + case SOAP_CLI_FAULT: + *s = "Client fault"; + break; + case SOAP_SVR_FAULT: + *s = "Server fault"; + break; + case SOAP_TAG_MISMATCH: + *s = soap_set_validation_fault(soap, "tag name or namespace mismatch", NULL); + break; + case SOAP_TYPE: + *s = soap_set_validation_fault(soap, "data type mismatch ", soap->type); + break; + case SOAP_SYNTAX_ERROR: + *s = "Well-formedness violation"; + break; + case SOAP_NO_TAG: + *s = "No XML element tag"; + break; + case SOAP_MUSTUNDERSTAND: + *c = "SOAP-ENV:MustUnderstand"; + sprintf(soap->msgbuf, "The data in element '%s' must be understood but cannot be handled", soap->tag); + *s = soap->msgbuf; + break; + case SOAP_VERSIONMISMATCH: + *c = "SOAP-ENV:VersionMismatch"; + *s = "Invalid SOAP message or SOAP version mismatch"; + break; + case SOAP_DATAENCODINGUNKNOWN: + *c = "SOAP-ENV:DataEncodingUnknown"; + *s = "Unsupported SOAP data encoding"; + break; + case SOAP_NAMESPACE: + *s = soap_set_validation_fault(soap, "namespace error", NULL); + break; + case SOAP_USER_ERROR: + *s = "User error"; + break; + case SOAP_FATAL_ERROR: + *s = "Fatal error"; + break; + case SOAP_NO_METHOD: + sprintf(soap->msgbuf, "Method '%s' not implemented: method name or namespace not recognized", soap->tag); + *s = soap->msgbuf; + break; + case SOAP_NO_DATA: + *s = "Data required for operation"; + break; + case SOAP_GET_METHOD: + *s = "HTTP GET method not implemented"; + break; + case SOAP_EOM: + *s = "Out of memory"; + break; + case SOAP_MOE: + *s = "Memory overflow or memory corruption error"; + break; + case SOAP_HDR: + *s = "Header line too long"; + break; + case SOAP_IOB: + *s = "Array index out of bounds"; + break; + case SOAP_NULL: + *s = soap_set_validation_fault(soap, "nil not allowed", NULL); + break; + case SOAP_DUPLICATE_ID: + *s = soap_set_validation_fault(soap, "multiple definitions of id ", soap->id); + if (soap->version == 2) + *soap_faultsubcode(soap) = "SOAP-ENC:DuplicateID"; + break; + case SOAP_MISSING_ID: + *s = soap_set_validation_fault(soap, "missing id for ref ", soap->id); + if (soap->version == 2) + *soap_faultsubcode(soap) = "SOAP-ENC:MissingID"; + break; + case SOAP_HREF: + *s = soap_set_validation_fault(soap, "incompatible object type ref/id pair ", soap->id); + break; + case SOAP_FAULT: + break; +#ifndef WITH_NOIO + case SOAP_UDP_ERROR: + *s = "Message too large for UDP packet"; + break; + case SOAP_TCP_ERROR: + *s = tcp_error(soap); + break; +#endif + case SOAP_HTTP_ERROR: + *s = "An HTTP processing error occurred"; + break; + case SOAP_SSL_ERROR: +#ifdef WITH_OPENSSL + *s = "SSL error"; +#else + *s = "OpenSSL not installed: recompile with -DWITH_OPENSSL"; +#endif + break; + case SOAP_PLUGIN_ERROR: + *s = "Plugin registry error"; + break; + case SOAP_DIME_ERROR: + *s = "DIME format error"; + break; + case SOAP_DIME_HREF: + *s = "DIME href to missing attachment"; + break; + case SOAP_DIME_MISMATCH: + *s = "DIME version/transmission error"; + break; + case SOAP_DIME_END: + *s = "End of DIME error"; + break; + case SOAP_MIME_ERROR: + *s = "MIME format error"; + break; + case SOAP_MIME_HREF: + *s = "MIME href to missing attachment"; + break; + case SOAP_MIME_END: + *s = "End of MIME error"; + break; + case SOAP_ZLIB_ERROR: +#ifdef WITH_ZLIB + sprintf(soap->msgbuf, "Zlib/gzip error: '%s'", soap->d_stream.msg?soap->d_stream.msg:""); + *s = soap->msgbuf; +#else + *s = "Zlib/gzip not installed for (de)compression: recompile with -DWITH_GZIP"; +#endif + break; + case SOAP_REQUIRED: + *s = soap_set_validation_fault(soap, "missing required attribute", NULL); + break; + case SOAP_PROHIBITED: + *s = soap_set_validation_fault(soap, "prohibited attribute present", NULL); + break; + case SOAP_OCCURS: + *s = soap_set_validation_fault(soap, "occurrence violation", NULL); + break; + case SOAP_LENGTH: + *s = soap_set_validation_fault(soap, "content length violation", NULL); + break; + case SOAP_FD_EXCEEDED: + *s = "Maximum number of open connections was reached"; + break; + case SOAP_STOP: + *s = "Stopped: no response sent"; + break; +#endif + case SOAP_EOF: +#ifndef WITH_NOIO + strcpy(soap->msgbuf, soap_strerror(soap)); +#ifndef WITH_LEAN + if (strlen(soap->msgbuf) + 25 < sizeof(soap->msgbuf)) + { memmove(soap->msgbuf + 25, soap->msgbuf, strlen(soap->msgbuf) + 1); + memcpy(soap->msgbuf, "End of file or no input: ", 25); + } +#endif + *s = soap->msgbuf; + break; +#else + *s = "End of file or no input"; + break; +#endif + default: +#ifndef WITH_NOHTTP +#ifndef WITH_LEAN + if (soap->error > 200 && soap->error < 600) + { sprintf(soap->msgbuf, "HTTP Error: %d %s", soap->error, http_error(soap, soap->error)); + *s = soap->msgbuf; + } + else +#endif +#endif + { sprintf(soap->msgbuf, "Error %d", soap->error); + *s = soap->msgbuf; + } + } +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send_fault(struct soap *soap) +{ register int status = soap->error; + int r = 1; + if (status == SOAP_STOP) + return status; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Sending back fault struct for error code %d\n", soap->error)); + soap->keep_alive = 0; /* to terminate connection */ + soap_set_fault(soap); +#ifndef WITH_NOIO +#ifndef WITH_LEAN + if (soap_valid_socket(soap->socket)) + { struct timeval timeout; + fd_set rfd, sfd; + timeout.tv_sec = 0; + timeout.tv_usec = 0; + FD_ZERO(&rfd); + FD_ZERO(&sfd); + FD_SET(soap->socket, &rfd); + FD_SET(soap->socket, &sfd); + r = select((int)soap->socket + 1, &rfd, &sfd, NULL, &timeout); + if (r > 0) + { if (!FD_ISSET(soap->socket, &sfd) + || (FD_ISSET(soap->socket, &rfd) + && recv(soap->socket, soap->tmpbuf, 1, MSG_PEEK) < 0)) + r = 0; + } + } +#endif +#endif + if ((status != SOAP_EOF || (!soap->recv_timeout && !soap->send_timeout)) && r > 0) + { soap->error = SOAP_OK; + soap_serializeheader(soap); + soap_serializefault(soap); + soap_begin_count(soap); + if (soap->mode & SOAP_IO_LENGTH) + { soap_envelope_begin_out(soap); + soap_putheader(soap); + soap_body_begin_out(soap); + soap_putfault(soap); + soap_body_end_out(soap); + soap_envelope_end_out(soap); + } + soap_end_count(soap); + if (soap_response(soap, status) + || soap_envelope_begin_out(soap) + || soap_putheader(soap) + || soap_body_begin_out(soap) + || soap_putfault(soap) + || soap_body_end_out(soap) + || soap_envelope_end_out(soap)) + return soap_closesock(soap); + soap_end_send(soap); + } + soap->error = status; + return soap_closesock(soap); +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv_fault(struct soap *soap) +{ register int status = soap->error; + DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Receiving SOAP Fault\n")); + soap->error = SOAP_OK; + if (soap_getfault(soap)) + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Error: soap_get_soapfault() failed. Is this a SOAP message at all?\n")); + *soap_faultcode(soap) = (soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client"); + soap->error = status; + soap_set_fault(soap); + } + else + { register const char *s = *soap_faultcode(soap); + if (!soap_match_tag(soap, s, "SOAP-ENV:Server") || !soap_match_tag(soap, s, "SOAP-ENV:Receiver")) + status = SOAP_SVR_FAULT; + else if (!soap_match_tag(soap, s, "SOAP-ENV:Client") || !soap_match_tag(soap, s, "SOAP-ENV:Sender")) + status = SOAP_CLI_FAULT; + else if (!soap_match_tag(soap, s, "SOAP-ENV:MustUnderstand")) + status = SOAP_MUSTUNDERSTAND; + else if (!soap_match_tag(soap, s, "SOAP-ENV:VersionMismatch")) + status = SOAP_VERSIONMISMATCH; + else + { DBGLOG(TEST,SOAP_MESSAGE(fdebug, "Fault code %s\n", s)); + status = SOAP_FAULT; + } + if (soap_body_end_in(soap) + || soap_envelope_end_in(soap) + || soap_end_recv(soap)) + return soap_closesock(soap); + soap->error = status; + } + return soap_closesock(soap); +} +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_send_empty_response(struct soap *soap, int status) +{ register soap_mode m = soap->omode; + soap->count = 0; + if ((m & SOAP_IO) == SOAP_IO_CHUNK) + { soap->omode &= ~SOAP_IO_CHUNK; + soap->omode |= SOAP_IO_BUFFER; + } + if (soap_response(soap, status) || soap_end_send(soap)) + { soap->omode = m; + return soap_closesock(soap); + } + soap->omode = m; + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOHTTP +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_recv_empty_response(struct soap *soap) +{ if (soap_begin_recv(soap) || soap_end_recv(soap)) + { if (soap->error != 202) + return soap_closesock(soap); + soap->error = SOAP_OK; + } + return SOAP_OK; +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_NOIO +#ifndef PALM_1 +static const char* +soap_strerror(struct soap *soap) +{ register int err = soap->errnum; + if (err) + { +#ifndef WIN32 + return strerror(err); +#else +#ifndef UNDER_CE + DWORD len; + *soap->msgbuf = '\0'; + len = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)soap->msgbuf, (DWORD)sizeof(soap->msgbuf), NULL); +#else + DWORD i, len; + *soap->msgbuf = '\0'; + len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, 0, (LPTSTR)soap->msgbuf, (DWORD)(sizeof(soap->msgbuf)/sizeof(TCHAR)), NULL); + for (i = 0; i <= len; i++) + { if (((TCHAR*)soap->msgbuf)[i] < 0x80) + soap->msgbuf[i] = (char)((TCHAR*)soap->msgbuf)[i]; + else + soap->msgbuf[i] = '?'; + } +#endif + return soap->msgbuf; +#endif + } + return "Operation interrupted or timed out"; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_2 +static int +soap_set_error(struct soap *soap, const char *faultcode, const char *faultsubcode, const char *faultstring, const char *faultdetail, int soaperror) +{ *soap_faultcode(soap) = faultcode; + if (faultsubcode) + *soap_faultsubcode(soap) = faultsubcode; + *soap_faultstring(soap) = faultstring; + if (faultdetail && *faultdetail) + { register const char **s = soap_faultdetail(soap); + if (s) + *s = faultdetail; + } + return soap->error = soaperror; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_sender_error(struct soap *soap, const char *faultstring, const char *faultdetail, int soaperror) +{ return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", NULL, faultstring, faultdetail, soaperror); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_set_receiver_error(struct soap *soap, const char *faultstring, const char *faultdetail, int soaperror) +{ return soap_set_error(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", NULL, faultstring, faultdetail, soaperror); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +static int +soap_copy_fault(struct soap *soap, const char *faultcode, const char *faultsubcode, const char *faultstring, const char *faultdetail) +{ char *r = NULL, *s = NULL, *t = NULL; + if (faultsubcode) + r = soap_strdup(soap, faultsubcode); + if (faultstring) + s = soap_strdup(soap, faultstring); + if (faultdetail) + t = soap_strdup(soap, faultdetail); + return soap_set_error(soap, faultcode, r, s, t, SOAP_FAULT); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_sender_fault(struct soap *soap, const char *faultstring, const char *faultdetail) +{ return soap_sender_fault_subcode(soap, NULL, faultstring, faultdetail); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_sender_fault_subcode(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail) +{ return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Sender" : "SOAP-ENV:Client", faultsubcode, faultstring, faultdetail); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_receiver_fault(struct soap *soap, const char *faultstring, const char *faultdetail) +{ return soap_receiver_fault_subcode(soap, NULL, faultstring, faultdetail); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_receiver_fault_subcode(struct soap *soap, const char *faultsubcode, const char *faultstring, const char *faultdetail) +{ return soap_copy_fault(soap, soap->version == 2 ? "SOAP-ENV:Receiver" : "SOAP-ENV:Server", faultsubcode, faultstring, faultdetail); +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +#ifndef WITH_NOSTDLIB +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_print_fault(struct soap *soap, FILE *fd) +{ if (soap_check_state(soap)) + fprintf(fd, "Error: soap struct not initialized\n"); + else if (soap->error) + { const char *c, *v = NULL, *s, **d; + d = soap_faultcode(soap); + if (!*d) + soap_set_fault(soap); + c = *d; + if (soap->version == 2) + v = *soap_faultsubcode(soap); + s = *soap_faultstring(soap); + d = soap_faultdetail(soap); + fprintf(fd, "%s%d fault: %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, c, v ? v : "no subcode", s ? s : "[no reason]", d && *d ? *d : "[no detail]"); + } +} +#endif +#endif + +/******************************************************************************/ +#ifndef WITH_LEAN +#ifndef WITH_NOSTDLIB +SOAP_FMAC1 +char* +SOAP_FMAC2 +soap_sprint_fault(struct soap *soap, char *buf, size_t len) +{ if (soap_check_state(soap)) + strncpy(buf, "Error: soap struct not initialized", len); + else if (soap->error) + { const char *c, *v = NULL, *s, **d; + d = soap_faultcode(soap); + if (!*d) + soap_set_fault(soap); + c = *d; + if (soap->version == 2) + v = *soap_faultsubcode(soap); + s = *soap_faultstring(soap); + d = soap_faultdetail(soap); +#ifdef WIN32 + _snprintf +#else + snprintf +#endif + (buf, len, "%s%d fault: %s [%s]\n\"%s\"\nDetail: %s\n", soap->version ? "SOAP 1." : "Error ", soap->version ? (int)soap->version : soap->error, c, v ? v : "no subcode", s ? s : "[no reason]", d && *d ? *d : "[no detail]"); + } + return buf; +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +#ifndef WITH_NOSTDLIB +SOAP_FMAC1 +void +SOAP_FMAC2 +soap_print_fault_location(struct soap *soap, FILE *fd) +{ +#ifndef WITH_LEAN + int i, j, c1, c2; + if (soap->error && soap->bufidx <= soap->buflen && soap->buflen > 0 && soap->buflen <= SOAP_BUFLEN) + { i = (int)soap->bufidx - 1; + if (i <= 0) + i = 0; + c1 = soap->buf[i]; + soap->buf[i] = '\0'; + if ((int)soap->buflen >= i + 1024) + j = i + 1023; + else + j = (int)soap->buflen - 1; + c2 = soap->buf[j]; + soap->buf[j] = '\0'; + fprintf(fd, "%s%c\n\n", soap->buf, c1); + if (soap->bufidx < soap->buflen) + fprintf(fd, "%s\n", soap->buf + soap->bufidx); + soap->buf[i] = c1; + soap->buf[j] = c2; + } +#endif +} +#endif +#endif + +/******************************************************************************/ +#ifndef PALM_1 +SOAP_FMAC1 +int +SOAP_FMAC2 +soap_register_plugin_arg(struct soap *soap, int (*fcreate)(struct soap*, struct soap_plugin*, void*), void *arg) +{ register struct soap_plugin *p; + register int r; + if (!(p = (struct soap_plugin*)SOAP_MALLOC(soap, sizeof(struct soap_plugin)))) + return soap->error = SOAP_EOM; + p->id = NULL; + p->data = NULL; + p->fcopy = NULL; + p->fdelete = NULL; + r = fcreate(soap, p, arg); + if (!r && p->fdelete) + { p->next = soap->plugins; + soap->plugins = p; + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Registered '%s' plugin\n", p->id)); + return SOAP_OK; + } + DBGLOG(TEST, SOAP_MESSAGE(fdebug, "Could not register plugin '%s': plugin returned error %d (or fdelete callback not set)\n", p->id?p->id:"?", r)); + SOAP_FREE(soap, p); + return r; +} +#endif + +/******************************************************************************/ +#ifndef PALM_1 +static void * +fplugin(struct soap *soap, const char *id) +{ register struct soap_plugin *p; + for (p = soap->plugins; p; p = p->next) + if (p->id == id || !strcmp(p->id, id)) + return p->data; + return NULL; +} +#endif + +/******************************************************************************/ +#ifndef PALM_2 +SOAP_FMAC1 +void * +SOAP_FMAC2 +soap_lookup_plugin(struct soap *soap, const char *id) +{ return soap->fplugin(soap, id); +} +#endif + +/******************************************************************************/ +#ifdef __cplusplus +} +#endif + +/******************************************************************************\ + * + * C++ soap struct methods + * +\******************************************************************************/ + +#ifdef __cplusplus +#ifndef WITH_LEAN +soap::soap() +{ soap_init(this); +} +#endif +#endif + +/******************************************************************************/ +#ifdef __cplusplus +#ifndef WITH_LEAN +soap::soap(soap_mode m) +{ soap_init1(this, m); +} +#endif +#endif + +/******************************************************************************/ +#ifdef __cplusplus +#ifndef WITH_LEAN +soap::soap(soap_mode im, soap_mode om) +{ soap_init2(this, im, om); +} +#endif +#endif + +/******************************************************************************/ +#ifdef __cplusplus +#ifndef WITH_LEAN +soap::soap(struct soap& soap) +{ soap_copy_context(this, &soap); +} +#endif +#endif + +/******************************************************************************/ +#ifdef __cplusplus +#ifndef WITH_LEAN +soap::~soap() +{ soap_destroy(this); + soap_end(this); + soap_done(this); +} +#endif +#endif + +/******************************************************************************/ diff --git a/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.9l.h b/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.9l.h new file mode 100644 index 0000000..dca1cde --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/src/stdsoap2_2.7.9l.h @@ -0,0 +1,2229 @@ +/* + +stdsoap2.h 2.7.9l + +gSOAP runtime + +gSOAP XML Web services tools +Copyright (C) 2000-2007, Robert van Engelen, Genivia Inc., All Rights Reserved. +This part of the software is released under one of the following licenses: +GPL, the gSOAP public license, or Genivia's license for commercial use. +-------------------------------------------------------------------------------- +Contributors: + +Wind River Systems, Inc., for the following additions (marked WR[...]): + - vxWorks compatible +-------------------------------------------------------------------------------- +gSOAP public license. + +The contents of this file are subject to the gSOAP Public License Version 1.3 +(the "License"); you may not use this file except in compliance with the +License. You may obtain a copy of the License at +http://www.cs.fsu.edu/~engelen/soaplicense.html +Software distributed under the License is distributed on an "AS IS" basis, +WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License +for the specific language governing rights and limitations under the License. + +The Initial Developer of the Original Code is Robert A. van Engelen. +Copyright (C) 2000-2007, Robert van Engelen, Genivia Inc., All Rights Reserved. +-------------------------------------------------------------------------------- +GPL license. + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA + +Author contact information: +engelen@genivia.com / engelen@acm.org +-------------------------------------------------------------------------------- +A commercial use license is available from Genivia, Inc., contact@genivia.com +-------------------------------------------------------------------------------- +*/ + +#ifdef WITH_SOAPDEFS_H +# include "soapdefs.h" /* include user-defined stuff */ +#endif + +#ifndef _THREAD_SAFE +# define _THREAD_SAFE +#endif + +#ifndef OPENSERVER +# ifndef _REENTRANT +# define _REENTRANT +# endif +#endif + +#ifndef SOAP_FMAC1 /* stdsoap2.h declaration macro */ +# define SOAP_FMAC1 +#endif + +#ifndef SOAP_FMAC2 /* stdsoap2.h declaration macro */ +# define SOAP_FMAC2 +#endif + +#ifndef SOAP_FMAC3 /* (de)serializer declaration macro */ +# define SOAP_FMAC3 +#endif + +#ifndef SOAP_FMAC3S /* string converter for (de)serializer declaration macro */ +# define SOAP_FMAC3S SOAP_FMAC3 +#endif + +#ifndef SOAP_FMAC4 /* (de)serializer declaration macro */ +# define SOAP_FMAC4 +#endif + +#ifndef SOAP_FMAC4S /* string converter for (de)serializer declaration macro */ +# define SOAP_FMAC4S SOAP_FMAC4 +#endif + +#ifndef SOAP_FMAC5 /* stub/skeleton declaration macro */ +# define SOAP_FMAC5 +#endif + +#ifndef SOAP_FMAC6 /* stub/skeleton declaration macro */ +# define SOAP_FMAC6 +#endif + +#ifndef SOAP_CMAC /* class declaration macro */ +# define SOAP_CMAC +#endif + +#ifndef SOAP_NMAC /* namespace table declaration macro */ +# define SOAP_NMAC +#endif + +#ifndef SOAP_SOURCE_STAMP +# define SOAP_SOURCE_STAMP(str) +#endif + +/* gSOAP 2.7.4 and higher: fast look-aside buffering is stable */ +#ifndef WITH_FAST +# define WITH_FAST +#endif + +#ifdef WITH_LEANER +# ifndef WITH_LEAN +# define WITH_LEAN +# endif +#endif + +#ifdef WITH_LEAN +# ifdef WITH_COOKIES +# error "Cannot build WITH_LEAN code WITH_COOKIES enabled" +# endif +#endif + +#ifndef STDSOAP_H +#define STDSOAP_H + +#if defined(__vxworks) || defined(__VXWORKS__) +# define VXWORKS +#endif + +#ifdef _WIN32 +# ifndef WIN32 +# define WIN32 +# endif +#endif + +#ifdef _WIN32_WCE +# ifndef UNDER_CE +# define UNDER_CE _WIN32_WCE +# endif +#endif + +#ifdef UNDER_CE +# ifndef WIN32 +# define WIN32 +# endif +#endif + +#ifdef __BORLANDC__ +# ifdef __WIN32__ +# ifndef WIN32 +# define WIN32 +# endif +# endif +#endif + +#ifdef __CYGWIN__ +# ifndef CYGWIN +# define CYGWIN +# endif +#endif + +#ifdef __SYMBIAN32__ +# define SYMBIAN +# undef WIN32 +#endif + +#if defined(__palmos__) || defined(PALM_GCC) || defined(__PALMOS_TRAPS__) +# ifndef PALM +# define PALM +# endif +#endif + +#if defined(__hpux) +# ifndef HP_UX +# define HP_UX +# endif +#endif + +#if defined(__digital__) && defined(__unix__) +# ifndef TRU64 +# define TRU64 +# endif +#endif + +#ifdef __MVS__ +# ifndef OS390 +# define OS390 +# endif +#endif + +#ifdef HAVE_CONFIG_H +# include "config.h" +# ifdef WITH_OPENSSL +# ifndef HAVE_OPENSSL_SSL_H +# undef WITH_OPENSSL +# endif +# endif +#else +# if defined(UNDER_CE) +# define WITH_NOEMPTYSTRUCT +# define WITH_LEAN +# define HAVE_SSCANF +# elif defined(WIN32) +# define WITH_NOEMPTYSTRUCT +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# define SOAP_LONG_FORMAT "%I64d" +# define SOAP_ULONG_FORMAT "%I64u" +# elif defined(CYGWIN) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(__APPLE__) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_TIMEGM +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(_AIX43) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(_AIX41) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(HP_UX) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(FREEBSD) || defined(__FreeBSD__) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_STRTOLL +# define HAVE_STRTOULL +# define HAVE_GETTIMEOFDAY +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# define SOAP_LONG_FORMAT "%qd" +# define SOAP_ULONG_FORMAT "%qu" +# elif defined(__VMS) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(__GLIBC__) || defined(__GNU__) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_STRTOLL +# define HAVE_STRTOULL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_TIMEGM +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# define HAVE_ISNAN +# elif defined(TRU64) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_GETTIMEOFDAY +# define HAVE_SYS_TIMEB_H +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define __USE_STD_IOSTREAM +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# define SOAP_LONG_FORMAT "%ld" +# define SOAP_ULONG_FORMAT "%lu" +# elif defined(MAC_CARBON) +# define WITH_NOIO +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GETHOSTBYNAME_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(PALM) +# define WITH_LEAN +# define HAVE_STRTOD /* strtod() is defined in palmFunctions.h */ +# include /* Needs to be included before unix headers */ +# include +# define IGNORE_STDIO_STUBS +# include +# define O_NONBLOCK FNONBIO +# include +# include "palmFunctions.h" +# elif defined(SYMBIAN) +# define WITH_LEAN +# define WITH_NONAMESPACES +# define HAVE_STRTOD /* use STRTOD since sscanf doesn't seem to work */ +# include +# include +# elif defined(VXWORKS) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_PGMTIME_R +# define HAVE_PLOCALTIME_R +# define HAVE_MKTIME +# elif defined(OS390) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(AS400) +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# elif defined(__QNX__) || defined(QNX) +/* QNX does not have a working version of strtof */ +# undef HAVE_STRTOF +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GETHOSTBYNAME_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# define LONG64 long +# define ULONG64 unsigned LONG64 +# define SOAP_LONG_FORMAT "%ld" +# define SOAP_ULONG_FORMAT "%lu" +# else +/* Default asumptions on supported functions */ +# define HAVE_STRRCHR +# define HAVE_STRTOD +# define HAVE_SSCANF +# define HAVE_STRTOL +# define HAVE_STRTOUL +# define HAVE_SYS_TIMEB_H +# define HAVE_FTIME +# define HAVE_RAND_R +# define HAVE_GETHOSTBYNAME_R +# define HAVE_GMTIME_R +# define HAVE_LOCALTIME_R +# define HAVE_WCTOMB +# define HAVE_MBTOWC +# endif +#endif + +#ifndef WITH_NOSTDLIB +# include +# ifndef PALM +# include +# include +# endif +# include +# include +#endif + +#if defined(__cplusplus) && !defined(WITH_LEAN) +# include +# include +#endif + +#ifdef WITH_NOHTTP +# ifndef WITH_NOIO +# define WITH_NOIO +# undef WITH_COOKIES +# endif +#endif + +/* Suggestion when SOAP_FD_EXCEEDED error occurs: + Some systems allow increasing FD_SETSIZE before including sys/types.h: +#define FD_SETSIZE (2048) +*/ + +#ifndef UNDER_CE +# ifndef PALM +# ifndef WITH_NOIO +# include +# include +# endif +# ifndef WITH_LEAN +# ifdef HAVE_SYS_TIMEB_H +# include /* for ftime() */ +# endif +# include +# endif +# endif +#endif + +#ifdef OPENSERVER +# include +# include +# include + extern int h_errno; +#endif + +#ifndef WITH_NOIO +# ifndef WIN32 +# ifndef PALM +# include +# ifdef VXWORKS +# include +# include +# endif +# ifndef VXWORKS +# ifndef SYMBIAN +# include +# endif +# endif +# ifdef SUN_OS +# include /* SUN */ +# include /* SUN < 2.8 (?) */ +# endif +# ifdef VXWORKS +# ifdef _WRS_KERNEL +# include +# endif +# else +# include +# endif +# include +# ifdef OS390 +# include +# else +# include /* TCP_NODELAY */ +# endif +# include +# endif +# endif +#endif + +#ifdef WIN32 +# ifndef UNDER_CE +# include +# include +# endif +# ifdef WITH_IPV6 +# include /* Visual Studio 2005 users: you must install the Platform SDK (R2) */ +# include +# include +# define SOAP_GAI_STRERROR gai_strerrorA +# else +# include /* Visual Studio 2005 users: you must install the Platform SDK (R2) */ +/* # include */ /* Alternative: use winsock2 (not available with eVC) */ +# endif +#else +# ifdef VXWORKS +# include +# include +# include +# endif +# ifndef WITH_NOIO +# ifndef PALM +# include +# include +# include +# include +# ifdef _AIX41 +# include +# endif +# endif +# endif +#endif + +#ifdef WITH_FASTCGI +# include +#endif + +#ifdef WITH_OPENSSL +# define OPENSSL_NO_KRB5 +# include +# include +# include +# include +# include +# ifndef ALLOW_OLD_VERSIONS +# if (OPENSSL_VERSION_NUMBER < 0x00905100L) +# error "Must use OpenSSL 0.9.6 or later" +# endif +# endif +#endif + +#ifdef WITH_GZIP +# ifndef WITH_ZLIB +# define WITH_ZLIB +# endif +#endif + +#ifdef WITH_CASEINSENSITIVETAGS +# define SOAP_STRCMP soap_tag_cmp /* case insensitve XML element/attribute names */ +#else +# define SOAP_STRCMP strcmp /* case sensitive XML element/attribute names */ +#endif + +#ifdef WITH_ZLIB +# include +#endif + +#ifndef WITH_NOSTDLIB +# ifndef PALM +# include /* for isnan() */ +# endif +#endif + +/* #define DEBUG */ /* Uncomment to debug sending (in file SENT.log) receiving (in file RECV.log) and messages (in file TEST.log) */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Portability: define SOAP_SOCKLEN_T */ +#if defined(_AIX) +# if defined(_AIX43) +# define SOAP_SOCKLEN_T socklen_t +# else +# define SOAP_SOCKLEN_T int +# endif +#elif defined(SOCKLEN_T) +# define SOAP_SOCKLEN_T SOCKLEN_T +#elif defined(__socklen_t_defined) || defined(_SOCKLEN_T) || defined(CYGWIN) || defined(FREEBSD) || defined(__FreeBSD__) || defined(__QNX__) || defined(QNX) +# define SOAP_SOCKLEN_T socklen_t +#elif defined(IRIX) || defined(WIN32) || defined(__APPLE__) || defined(HP_UX) || defined(SUN_OS) || defined(OPENSERVER) || defined(TRU64) || defined(VXWORKS) +# define SOAP_SOCKLEN_T int +#else +# define SOAP_SOCKLEN_T size_t +#endif + +#ifndef SOAP_SOCKET +# ifdef WIN32 +# define SOAP_SOCKET SOCKET +# define soap_closesocket(n) closesocket(n) +# else +# define SOAP_SOCKET int +# define soap_closesocket(n) close(n) +# endif +#endif + +#define SOAP_INVALID_SOCKET (-1) +#define soap_valid_socket(n) ((n) != SOAP_INVALID_SOCKET) + +#ifndef SOAP_GAI_STRERROR +# define SOAP_GAI_STRERROR gai_strerror +#endif + +#ifndef FD_SETSIZE +# define FD_SETSIZE (1024) +#endif + +#if defined(SYMBIAN) +# define LONG64 long +# define ULONG64 unsigned LONG64 +#elif !defined(WIN32) || defined(CYGWIN) || defined(__GLIBC__) || defined(__GNU__) +# ifndef LONG64 +# if defined(__GLIBC__) +# include +# if (__WORDSIZE == 64) +# define LONG64 int64_t +# define ULONG64 uint64_t +# ifndef SOAP_LONG_FORMAT +# define SOAP_LONG_FORMAT "%ld" +# endif +# ifndef SOAP_ULONG_FORMAT +# define SOAP_ULONG_FORMAT "%lu" +# endif +# else +# define LONG64 long long +# define ULONG64 unsigned LONG64 +# endif +# else +# define LONG64 long long +# define ULONG64 unsigned LONG64 +# endif +# endif +#elif defined(UNDER_CE) +# define LONG64 __int64 +# define ULONG64 unsigned LONG64 +#elif defined(__BORLANDC__) +# define LONG64 __int64 +# define ULONG64 unsigned LONG64 +#endif + +#ifndef SOAP_LONG_FORMAT +# define SOAP_LONG_FORMAT "%lld" /* printf format for 64 bit ints */ +#endif + +#ifndef SOAP_ULONG_FORMAT +# define SOAP_ULONG_FORMAT "%llu" /* printf format for unsigned 64 bit ints */ +#endif + +#if defined(WIN32) && !defined(CYGWIN) +# define soap_int32 __int32 +#elif defined(SYMBIAN) +# define soap_int32 long +#elif defined(PALM) +# define soap_int32 Int32 +#elif defined(_AIX) +# if defined(_AIX43) +# define soap_int32 int32_t +# else +# define soap_int32 signed int +# endif +#else +# define soap_int32 int32_t +#endif + +#ifdef WIN32 +# define SOAP_ERANGE ERANGE +# define SOAP_EINTR WSAEINTR +# define SOAP_EAGAIN WSAEWOULDBLOCK +# define SOAP_EWOULDBLOCK WSAEWOULDBLOCK +# define SOAP_EINPROGRESS WSAEINPROGRESS +# define SOAP_EADDRINUSE WSAEADDRINUSE +#else +# define SOAP_ERANGE ERANGE +# define SOAP_EINTR EINTR +# define SOAP_EAGAIN EAGAIN +# define SOAP_EADDRINUSE EADDRINUSE +# ifdef SYMBIAN +# define SOAP_EWOULDBLOCK 9898 +# define SOAP_EINPROGRESS 9899 +# else +# define SOAP_EWOULDBLOCK EWOULDBLOCK +# define SOAP_EINPROGRESS EINPROGRESS +# endif +#endif + +#ifdef WIN32 +# ifdef UNDER_CE +# define soap_errno GetLastError() +# define soap_socket_errno(s) GetLastError() +# define soap_reset_errno SetLastError(0) +# else +# define soap_errno GetLastError() +# define soap_socket_errno(s) WSAGetLastError() +# define soap_reset_errno SetLastError(0) +# endif +#else +# ifndef WITH_NOIO +# define soap_errno errno +# define soap_socket_errno(s) errno +# define soap_reset_errno (errno = 0) +# else +# define soap_errno 0 +# define soap_socket_errno(s) 0 +# define soap_reset_errno +# endif +#endif + +#ifndef SOAP_BUFLEN +# ifdef WITH_UDP +# define SOAP_BUFLEN (65536) /* max UDP packet size */ +# else +# ifndef WITH_LEAN +# define SOAP_BUFLEN (65536) /* buffer length for socket packets, also used by gethostbyname_r so don't make this too small */ +# else +# define SOAP_BUFLEN (2048) +# endif +# endif +#endif +#ifndef SOAP_LABLEN +# define SOAP_LABLEN (256) /* initial look-aside buffer length */ +#endif +#ifndef SOAP_PTRBLK +# define SOAP_PTRBLK (32) /* block allocation for pointer hash table chains */ +#endif +#ifndef SOAP_PTRHASH +# ifndef WITH_LEAN +# define SOAP_PTRHASH (1024) /* size of pointer analysis hash table (must be power of 2) */ +# else +# define SOAP_PTRHASH (32) +# endif +#endif +#ifndef SOAP_IDHASH +# ifndef WITH_LEAN +# define SOAP_IDHASH (1999) /* prime size of hash table for parsed id/ref */ +# else +# define SOAP_IDHASH (19) /* 19, 199 */ +# endif +#endif +#ifndef SOAP_BLKLEN +# ifndef WITH_LEAN +# define SOAP_BLKLEN (256) /* size of blocks to collect long strings and XML attributes */ +# else +# define SOAP_BLKLEN (32) +# endif +#endif +#ifndef SOAP_TAGLEN +# ifndef WITH_LEAN +# define SOAP_TAGLEN (1024) /* maximum length of XML element tag/attribute name or host/path name + 1 */ +# else +# define SOAP_TAGLEN (64) +# endif +#endif +#ifndef SOAP_HDRLEN +# ifndef WITH_LEAN +# define SOAP_HDRLEN (8192) /* maximum length of HTTP header line (must be >4096 to read cookies) */ +# else +# define SOAP_HDRLEN (1024) +# endif +#endif +#ifndef SOAP_MAXDIMS +# ifndef WITH_LEAN +# define SOAP_MAXDIMS (16) /* maximum array dimensions (array nestings) must be less than 64 to protect soap->tmpbuf */ +# else +# define SOAP_MAXDIMS (4) +# endif +#endif + +#ifndef SOAP_MAXLOGS +# define SOAP_MAXLOGS (3) /* max number of debug logs per struct soap environment */ +# define SOAP_INDEX_RECV (0) +# define SOAP_INDEX_SENT (1) +# define SOAP_INDEX_TEST (2) +#endif + +#ifndef SOAP_MAXKEEPALIVE +# define SOAP_MAXKEEPALIVE (100) /* max iterations to keep server connection alive */ +#endif + +#ifndef SOAP_MAXARRAYSIZE +# define SOAP_MAXARRAYSIZE (100000) /* "trusted" max size of inbound SOAP array for compound array allocation */ +#endif + +#ifdef VXWORKS +# ifdef __INCmathh +# include +# ifndef HAVE_ISNAN +# define HAVE_ISNAN +# endif +# define soap_isnan(num) isNan(num) +# endif +#endif + +#ifdef WIN32 +# include +# ifndef HAVE_ISNAN +# define HAVE_ISNAN +# endif +# define soap_isnan(num) _isnan(num) +#endif + +#ifdef SUN_OS +# define HAVE_ISNAN +#endif + +#ifdef __APPLE__ +# ifdef __cplusplus +# ifndef isnan +extern "C" int isnan(double); +# endif +# endif +# define HAVE_ISNAN +#endif + +#if !defined(HAVE_ISNAN) && (defined(_MATH_H) || defined(_MATH_INCLUDED)) +# define HAVE_ISNAN +#endif + +extern const struct soap_double_nan { unsigned int n1, n2; } soap_double_nan; + +#ifdef VXWORKS +# ifndef FLT_MAX +# define FLT_MAX _ARCH_FLT_MAX +# endif +# ifndef DBL_MAX +# define DBL_MAX _ARCH_DBL_MAX +# endif +#endif + +#ifndef FLT_NAN +# define FLT_NAN (*(float*)(void*)&soap_double_nan) +#endif + +#ifndef FLT_PINFTY +# if defined(FLT_MAX) +# define FLT_PINFTY FLT_MAX +# elif defined(HUGE_VALF) +# define FLT_PINFTY (float)HUGE_VALF +# elif defined(HUGE_VAL) +# define FLT_PINFTY (float)HUGE_VAL +# elif defined(FLOAT_MAX) +# define FLT_PINFTY FLOAT_MAX +# else +# define FLT_PINFTY (3.40282347e+38F) +# endif +#endif + +#ifndef FLT_NINFTY +# define FLT_NINFTY (-FLT_PINFTY) +#endif + +#ifndef DBL_NAN +# define DBL_NAN (*(double*)(void*)&soap_double_nan) +#endif + +#ifndef DBL_PINFTY +# if defined(DBL_MAX) +# define DBL_PINFTY DBL_MAX +# elif defined(HUGE_VALF) +# define DBL_PINFTY (double)HUGE_VALF +# elif defined(HUGE_VAL) +# define DBL_PINFTY (double)HUGE_VAL +# elif defined(DOUBLE_MAX) +# define DBL_PINFTY DOUBLE_MAX +# else +# define DBL_PINFTY (1.7976931348623157e+308) +# endif +#endif + +#ifndef DBL_NINFTY +# define DBL_NINFTY (-DBL_PINFTY) +#endif + +#ifndef soap_isnan +# ifdef HAVE_ISNAN +# define soap_isnan(n) isnan(n) +# else +# define soap_isnan(n) (0) +# endif +#endif + +#define soap_ispinfd(n) ((n) >= DBL_PINFTY) +#define soap_ispinff(n) ((n) >= FLT_PINFTY) +#define soap_isninfd(n) ((n) <= DBL_NINFTY) +#define soap_isninff(n) ((n) <= FLT_NINFTY) + +/* gSOAP error codes */ + +#define SOAP_EOF EOF +#define SOAP_ERR EOF +#define SOAP_OK 0 +#define SOAP_CLI_FAULT 1 +#define SOAP_SVR_FAULT 2 +#define SOAP_TAG_MISMATCH 3 +#define SOAP_TYPE 4 +#define SOAP_SYNTAX_ERROR 5 +#define SOAP_NO_TAG 6 +#define SOAP_IOB 7 +#define SOAP_MUSTUNDERSTAND 8 +#define SOAP_NAMESPACE 9 +#define SOAP_USER_ERROR 10 +#define SOAP_FATAL_ERROR 11 +#define SOAP_FAULT 12 +#define SOAP_NO_METHOD 13 +#define SOAP_NO_DATA 14 +#define SOAP_GET_METHOD 15 +#define SOAP_EOM 16 +#define SOAP_MOE 17 +#define SOAP_HDR 18 +#define SOAP_NULL 19 +#define SOAP_DUPLICATE_ID 20 +#define SOAP_MISSING_ID 21 +#define SOAP_HREF 22 +#define SOAP_UDP_ERROR 23 +#define SOAP_TCP_ERROR 24 +#define SOAP_HTTP_ERROR 25 +#define SOAP_SSL_ERROR 26 +#define SOAP_ZLIB_ERROR 27 +#define SOAP_DIME_ERROR 28 +#define SOAP_DIME_HREF 29 +#define SOAP_DIME_MISMATCH 30 +#define SOAP_DIME_END 31 +#define SOAP_MIME_ERROR 32 +#define SOAP_MIME_HREF 33 +#define SOAP_MIME_END 34 +#define SOAP_VERSIONMISMATCH 35 +#define SOAP_PLUGIN_ERROR 36 +#define SOAP_DATAENCODINGUNKNOWN 37 +#define SOAP_REQUIRED 38 +#define SOAP_PROHIBITED 39 +#define SOAP_OCCURS 40 +#define SOAP_LENGTH 41 +#define SOAP_FD_EXCEEDED 42 + +#define soap_xml_error_check(e) ((e) == SOAP_TAG_MISMATCH || (e) == SOAP_NO_TAG || (e) == SOAP_SYNTAX_ERROR || (e) == SOAP_NAMESPACE || (e) == SOAP_DUPLICATE_ID || (e) == SOAP_MISSING_ID || (e) == SOAP_REQUIRED || (e) == SOAP_PROHIBITED || (e) == SOAP_OCCURS || (e) == SOAP_LENGTH || (e) == SOAP_NULL || (e) == SOAP_HREF) +#define soap_soap_error_check(e) ((e) == SOAP_CLI_FAULT || (e) == SOAP_SVR_FAULT || (e) == SOAP_VERSIONMISMATCH || (e) == SOAP_MUSTUNDERSTAND || (e) == SOAP_FAULT || (e) == SOAP_NO_METHOD) +#define soap_tcp_error_check(e) ((e) == SOAP_EOF || (e) == SOAP_TCP_ERROR) +#define soap_ssl_error_check(e) ((e) == SOAP_SSL_ERROR) +#define soap_zlib_error_check(e) ((e) == SOAP_ZLIB_ERROR) +#define soap_http_error_check(e) ((e) == SOAP_HTTP_ERROR || (e) == SOAP_GET_METHOD || (e) == SOAP_NO_DATA || ((e) >= 100 && (e) < 600)) + +/* gSOAP HTTP response status codes 100 to 599 are reserved */ + +/* Codes 600 to 999 are user definable */ + +/* Exceptional gSOAP HTTP response status codes >= 1000 */ + +#define SOAP_STOP 1000 /* No HTTP response */ +#define SOAP_FORM 1001 /* Form request/response */ +#define SOAP_HTML 1002 /* Custom HTML response */ +#define SOAP_FILE 1003 /* Custom file-based response */ + +/* gSOAP HTTP method codes */ + +#define SOAP_POST 2000 +#define SOAP_GET 2001 + +/* gSOAP DIME */ + +#define SOAP_DIME_CF 0x01 +#define SOAP_DIME_ME 0x02 +#define SOAP_DIME_MB 0x04 +#define SOAP_DIME_VERSION 0x08 /* DIME version 1 */ +#define SOAP_DIME_MEDIA 0x10 +#define SOAP_DIME_ABSURI 0x20 + +/* gSOAP ZLIB */ + +#define SOAP_ZLIB_NONE 0x00 +#define SOAP_ZLIB_DEFLATE 0x01 +#define SOAP_ZLIB_INFLATE 0x02 +#define SOAP_ZLIB_GZIP 0x02 + +/* gSOAP transport, connection, and content encoding modes */ + +typedef soap_int32 soap_mode; + +#define SOAP_IO 0x00000003 /* IO mask */ +#define SOAP_IO_FLUSH 0x00000000 /* flush output immediately, no buffering */ +#define SOAP_IO_BUFFER 0x00000001 /* buffer output in packets of size SOAP_BUFLEN */ +#define SOAP_IO_STORE 0x00000002 /* store entire output to determine length for transport */ +#define SOAP_IO_CHUNK 0x00000003 /* use HTTP chunked transfer AND buffer packets */ + +#define SOAP_IO_UDP 0x00000004 /* TCP or UDP */ + +#define SOAP_IO_LENGTH 0x00000008 /* calc message length (internal) */ +#define SOAP_IO_KEEPALIVE 0x00000010 /* keep connection alive */ + +#define SOAP_ENC_LATIN 0x00000020 /* accept iso-8859-1 encoding */ +#define SOAP_ENC_XML 0x00000040 /* plain XML encoding, no HTTP header */ +#define SOAP_ENC_DIME 0x00000080 +#define SOAP_ENC_MIME 0x00000100 +#define SOAP_ENC_MTOM 0x00000200 +#define SOAP_ENC_ZLIB 0x00000400 +#define SOAP_ENC_SSL 0x00000800 + +#define SOAP_ENC 0x00000FFF /* IO and ENC mask */ + +#define SOAP_XML_STRICT 0x00001000 /* apply strict validation */ +#define SOAP_XML_INDENT 0x00002000 /* emit indented XML */ +#define SOAP_XML_CANONICAL 0x00004000 /* EXC C14N canonical XML */ +#define SOAP_XML_TREE 0x00008000 /* emit XML tree (no id/ref) */ +#define SOAP_XML_GRAPH 0x00010000 +#define SOAP_XML_NIL 0x00020000 +#define SOAP_XML_DOM 0x00040000 +#define SOAP_XML_SEC 0x00080000 /* reserved for WS security */ + +#define SOAP_C_NOIOB 0x00100000 /* don't fault on array index out of bounds (just ignore) */ +#define SOAP_C_UTFSTRING 0x00200000 /* (de)serialize strings with UTF8 content */ +#define SOAP_C_MBSTRING 0x00400000 /* (de)serialize strings with multi-byte content */ +#define SOAP_C_NILSTRING 0x00800000 /* serialize empty strings as nil (omitted) */ + +#define SOAP_DOM_TREE 0x01000000 +#define SOAP_DOM_NODE 0x02000000 +#define SOAP_DOM_ASIS 0x04000000 + +#define SOAP_MIME_POSTCHECK 0x10000000 /* MIME flag (internal) */ + +#define SOAP_IO_DEFAULT SOAP_IO_FLUSH + +/* SSL client/server authentication settings */ + +#define SOAP_SSL_NO_AUTHENTICATION 0x00 /* for testing purposes */ +#define SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION 0x01 /* client requires server to authenticate */ +#define SOAP_SSL_REQUIRE_CLIENT_AUTHENTICATION 0x02 /* server requires client to authenticate */ +#define SOAP_SSL_SKIP_HOST_CHECK 0x04 /* client does not check the common name of the host in certificate */ +#define SOAP_SSL_RSA 0x08 /* use RSA */ +#define SOAP_SSLv3_TLSv1 0x00 /* SSL v3 and TLS v1 support by default */ +#define SOAP_SSLv3 0x10 /* SSL v3 only */ +#define SOAP_TLSv1 0x20 /* TLS v1 only */ + +#define SOAP_SSL_DEFAULT (SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION | SOAP_SSLv3_TLSv1) + +/* state */ + +#define SOAP_INIT 1 +#define SOAP_COPY 2 + +#define soap_check_state(soap) (!(soap) || ((soap)->state != SOAP_INIT && (soap)->state != SOAP_COPY)) + +/* part */ + +#define SOAP_BEGIN 0 +#define SOAP_IN_ENVELOPE 2 +#define SOAP_IN_HEADER 3 +#define SOAP_END_HEADER 4 +#define SOAP_NO_BODY 5 +#define SOAP_IN_BODY 6 +#define SOAP_END_BODY 7 +#define SOAP_END_ENVELOPE 8 +#define SOAP_END 9 +#define SOAP_BEGIN_SECURITY 10 +#define SOAP_IN_SECURITY 11 +#define SOAP_END_SECURITY 12 + +/* DEBUG macros */ + +#ifndef WITH_LEAN +# ifdef DEBUG +# ifndef SOAP_DEBUG +# define SOAP_DEBUG +# endif +# ifndef SOAP_MEM_DEBUG +# define SOAP_MEM_DEBUG +# endif +# endif +#endif + +#ifdef SOAP_MEM_DEBUG +# ifndef SOAP_MALLOC +# define SOAP_MALLOC(soap, size) soap_track_malloc(soap, __FILE__, __LINE__, size) +# endif +# ifndef SOAP_FREE +# define SOAP_FREE(soap, ptr) soap_track_free(soap, __FILE__, __LINE__, ptr) +# endif +#endif + +#ifndef SOAP_MALLOC /* use libc malloc */ +# define SOAP_MALLOC(soap, size) malloc(size) +#endif + +#ifndef SOAP_FREE /* use libc free */ +# define SOAP_FREE(soap, ptr) free(ptr) +#endif + +#ifdef SOAP_DEBUG +# ifndef SOAP_MESSAGE +# define SOAP_MESSAGE fprintf +# endif +# ifndef DBGLOG +# define DBGLOG(DBGFILE, CMD) \ +{ if (soap)\ + { if (!soap->fdebug[SOAP_INDEX_##DBGFILE])\ + soap_open_logfile((struct soap*)soap, SOAP_INDEX_##DBGFILE);\ + if (soap->fdebug[SOAP_INDEX_##DBGFILE])\ + { FILE *fdebug = soap->fdebug[SOAP_INDEX_##DBGFILE];\ + CMD;\ + fflush(fdebug);\ + }\ + }\ +} +# endif +# ifndef DBGMSG +# define DBGMSG(DBGFILE, MSG, LEN) \ +{ if (soap)\ + { if (!soap->fdebug[SOAP_INDEX_##DBGFILE])\ + soap_open_logfile((struct soap*)soap, SOAP_INDEX_##DBGFILE);\ + if (soap->fdebug[SOAP_INDEX_##DBGFILE])\ + { fwrite((MSG), 1, (LEN), soap->fdebug[SOAP_INDEX_##DBGFILE]);\ + fflush(soap->fdebug[SOAP_INDEX_##DBGFILE]);\ + }\ + }\ +} +# endif +# ifndef DGBFUN +# define DBGFUN(FNAME) DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): %s()\n", __FILE__, __LINE__, FNAME)) +# define DBGFUN1(FNAME, FMT, ARG) DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): %s("FMT")\n", __FILE__, __LINE__, FNAME, (ARG))) +# define DBGFUN2(FNAME, FMT1, ARG1, FMT2, ARG2) DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): %s("FMT1", "FMT2")\n", __FILE__, __LINE__, FNAME, (ARG1), (ARG2))) +# define DBGFUN3(FNAME, FMT1, ARG1, FMT2, ARG2, FMT3, ARG3) DBGLOG(TEST, SOAP_MESSAGE(fdebug, "%s(%d): %s("FMT1", "FMT2", "FMT3")\n", __FILE__, __LINE__, FNAME, (ARG1), (ARG2), (ARG3))) +# endif +# ifndef DBGHEX +# define DBGHEX(DBGFILE, MSG, LEN) \ +{ if (soap)\ + { if (!soap->fdebug[SOAP_INDEX_##DBGFILE])\ + soap_open_logfile(soap, SOAP_INDEX_##DBGFILE);\ + if (soap->fdebug[SOAP_INDEX_##DBGFILE])\ + { int i; char *s;\ + for (s = (char*)(MSG), i = (LEN); i; i--)\ + fprintf(soap->fdebug[SOAP_INDEX_##DBGFILE], "%2.2X ", (int)*s++&0xFF);\ + fflush(soap->fdebug[SOAP_INDEX_##DBGFILE]);\ + }\ + }\ +} +# endif +#else +# define DBGLOG(DBGFILE, CMD) +# define DBGMSG(DBGFILE, MSG, LEN) +# define DBGFUN(FNAME) +# define DBGFUN1(FNAME, FMT, ARG) +# define DBGFUN2(FNAME, FMT1, ARG1, FMT2, ARG2) +# define DBGFUN3(FNAME, FMT1, ARG1, FMT2, ARG2, FMT3, ARG3) +# define DBGHEX(DBGFILE, MSG, LEN) +#endif + +/* UCS-4 requires 32 bits (0-7FFFFFFF, the sign bit is used by gSOAP to distinguish XML entities) */ +typedef soap_int32 soap_wchar; + +/* namespace table row */ +struct Namespace +{ const char *id; + const char *ns; + const char *in; + char *out; +}; + +/* namespace stack */ +struct soap_nlist +{ struct soap_nlist *next; + unsigned int level; /* nesting depth level */ + short index; /* corresponding entry in ns mapping table */ + char *ns; /* only set when parsed ns URI is not in the ns mapping table */ + char id[1]; /* the actual string value flows into the allocated region below this struct */ +}; + +/* block stack for nested block allocations */ +struct soap_blist +{ struct soap_blist *next; + char *ptr; + size_t size; +}; + +/* array layout */ +struct soap_array +{ void *__ptr; + int __size; +}; + +/* pointer serialization management */ +struct soap_plist +{ struct soap_plist *next; + const void *ptr; + const struct soap_array *array; + int type; + int id; + char mark1; + char mark2; +}; + +/* block allocation for pointer serialization management */ +struct soap_pblk +{ struct soap_pblk *next; + struct soap_plist plist[SOAP_PTRBLK]; +}; + +#ifdef SOAP_MEM_DEBUG +/* malloc/free tracking for debugging */ +struct soap_mlist +{ struct soap_mlist *next; + const void *ptr; + const char *file; + int line; + short live; +}; +#endif + +/* class allocation list */ +struct soap_clist +{ struct soap_clist *next; + void *ptr; + int type; + int size; + int (*fdelete)(struct soap_clist*); +}; + +/* attributes */ +struct soap_attribute +{ struct soap_attribute *next; + char *value; + size_t size; + char *ns; + short visible; + char name[1]; /* the actual name string flows into the allocated region below this struct */ +}; + +#ifndef WITH_LEAN +struct soap_cookie +{ struct soap_cookie *next; + char *name; + char *value; + char *domain; + char *path; + time_t expire; /* client-side: local time to expire */ + long maxage; /* server-side: seconds to expire */ + unsigned int version; + short secure; + short session; /* server-side */ + short env; /* server-side: got cookie from client and should not be (re)send */ + short modified; /* server-side: client cookie was modified and should be send */ +}; +#endif + +#ifdef __cplusplus +SOAP_FMAC1 struct soap_multipart* SOAP_FMAC2 soap_next_multipart(struct soap_multipart*); + +class soap_multipart_iterator +{ public: + struct soap_multipart *content; + bool operator==(const soap_multipart_iterator& iter) const + { return content == iter.content; } + bool operator!=(const soap_multipart_iterator& iter) const + { return content != iter.content; } + struct soap_multipart &operator*() const + { return *content; } + soap_multipart_iterator &operator++() + { content = soap_next_multipart(content); return *this; } + soap_multipart_iterator() : content(NULL) + { } + soap_multipart_iterator(struct soap_multipart *p) : content(p) + { } +}; +#endif + +#ifndef WITH_LEANER +struct soap_dime +{ size_t count; + size_t size; + size_t chunksize; + size_t buflen; + char flags; + char *ptr; + const char *id; + const char *type; + const char *options; + struct soap_multipart *list; /* list of DIME attachments received */ + struct soap_multipart *first, *last; /* temporary in/out queue */ +#ifdef __cplusplus + soap_multipart_iterator begin() + { soap_multipart_iterator iter(list); return iter; }; + soap_multipart_iterator end() + { soap_multipart_iterator iter(NULL); return iter; }; +#endif +}; +#endif + +#ifndef WITH_LEANER +struct soap_mime +{ char *boundary; /* MIME boundary */ + const char *start; /* MIME start ID */ + struct soap_multipart *list; /* list of MIME attachments received */ + struct soap_multipart *first, *last; /* temporary in/out queue */ +#ifdef __cplusplus + soap_multipart_iterator begin() + { soap_multipart_iterator iter(list); return iter; }; + soap_multipart_iterator end() + { soap_multipart_iterator iter(NULL); return iter; }; +#endif +}; +#endif + +#ifndef WITH_LEANER +/* RFC2045 MIME content transfer encodings */ +enum soap_mime_encoding +{ SOAP_MIME_NONE, + SOAP_MIME_7BIT, + SOAP_MIME_8BIT, + SOAP_MIME_BINARY, + SOAP_MIME_QUOTED_PRINTABLE, + SOAP_MIME_BASE64, + SOAP_MIME_IETF_TOKEN, + SOAP_MIME_X_TOKEN +}; +#endif + +#ifndef WITH_LEANER +/* DIME/MIME multipart list */ +struct soap_multipart +{ struct soap_multipart *next; + char *ptr; /* points to raw data content */ + size_t size; /* size of data content */ + const char *id; /* DIME/MIME content ID or form data name */ + const char *type; /* DIME/MIME type (MIME type format) */ + const char *options; /* DIME options */ + enum soap_mime_encoding encoding; /* MIME Content-Transfer-Encoding */ + const char *location; /* MIME Content-Location (optional) */ + const char *description; /* MIME Content-Description (optional) */ +#ifdef __cplusplus + typedef soap_multipart_iterator iterator; +#endif +}; +#endif + +#ifndef WITH_LEANER +/* attachment DIME and MTOM XOP forwarding */ +struct soap_xlist +{ struct soap_xlist *next; + unsigned char **ptr; + int *size; + char *id; + char **type; + char **options; +}; +#endif + +/******************************************************************************/ + +#ifndef WITH_LEANER +#ifdef __cplusplus +class soap_dom_attribute_iterator +{ public: + struct soap_dom_attribute *att; + const char *nstr; + const char *name; + bool operator==(const soap_dom_attribute_iterator&) const; + bool operator!=(const soap_dom_attribute_iterator&) const; + struct soap_dom_attribute &operator*() const; + soap_dom_attribute_iterator &operator++(); + soap_dom_attribute_iterator(); + soap_dom_attribute_iterator(struct soap_dom_attribute*); + ~soap_dom_attribute_iterator(); +}; +#endif +#endif + +#ifndef WITH_LEANER +struct soap_dom_attribute +{ struct soap_dom_attribute *next; + const char *nstr; + char *name; + char *data; + wchar_t *wide; + struct soap *soap; +#ifdef __cplusplus + typedef soap_dom_attribute_iterator iterator; + struct soap_dom_attribute &set(const char *nstr, const char *name); /* set namespace and name */ + struct soap_dom_attribute &set(const char *data); /* set data */ + soap_dom_attribute_iterator begin(); + soap_dom_attribute_iterator end(); + soap_dom_attribute_iterator find(const char *nstr, const char *name); + void unlink(); + soap_dom_attribute(); + soap_dom_attribute(struct soap *soap); + soap_dom_attribute(struct soap *soap, const char *nstr, const char *name, const char *data); + ~soap_dom_attribute(); +#endif +}; +#endif + +#ifndef WITH_LEANER +#ifdef __cplusplus +class soap_dom_element_iterator +{ public: + struct soap_dom_element *elt; + const char *nstr; + const char *name; + int type; + bool operator==(const soap_dom_element_iterator&) const; + bool operator!=(const soap_dom_element_iterator&) const; + struct soap_dom_element &operator*() const; + soap_dom_element_iterator &operator++(); + soap_dom_element_iterator(); + soap_dom_element_iterator(struct soap_dom_element*); + ~soap_dom_element_iterator(); +}; +#endif +#endif + +#ifndef WITH_LEANER +struct soap_dom_element +{ struct soap_dom_element *next; /* next sibling */ + struct soap_dom_element *prnt; /* parent */ + struct soap_dom_element *elts; /* list of child elements */ + struct soap_dom_attribute *atts; /* list of attributes */ + const char *nstr; /* namespace string */ + char *name; /* element tag name */ + char *data; /* element content data (with SOAP_C_UTFSTRING flag set) */ + wchar_t *wide; /* element content data */ + int type; /* optional: serialized C/C++ data type */ + void *node; /* optional: pointer to serialized C/C++ data */ + char *head; /* leading whitespace to start tag */ + char *tail; /* leading whitespace to end tag */ + struct soap *soap; /* soap context that manages this node */ +#ifdef __cplusplus + typedef soap_dom_element_iterator iterator; + struct soap_dom_element &set(const char *nstr, const char *name); + struct soap_dom_element &set(const char *data); + struct soap_dom_element &set(void *node, int type); + struct soap_dom_element &add(struct soap_dom_element*); + struct soap_dom_element &add(struct soap_dom_element&); + struct soap_dom_element &add(struct soap_dom_attribute*); + struct soap_dom_element &add(struct soap_dom_attribute&); + soap_dom_element_iterator begin(); + soap_dom_element_iterator end(); + soap_dom_element_iterator find(const char *nstr, const char *name); + soap_dom_element_iterator find(int type); + void unlink(); + soap_dom_element(); + soap_dom_element(struct soap *soap); + soap_dom_element(struct soap *soap, const char *nstr, const char *name); + soap_dom_element(struct soap *soap, const char *nstr, const char *name, const char *data); + soap_dom_element(struct soap *soap, const char *nstr, const char *name, void *node, int type); + ~soap_dom_element(); +#endif +}; +SOAP_FMAC1 struct soap_dom_element * SOAP_FMAC2 soap_dom_next_element(struct soap_dom_element *elt); +SOAP_FMAC1 struct soap_dom_attribute * SOAP_FMAC2 soap_dom_next_attribute(struct soap_dom_attribute *att); +#endif + +#if defined(__cplusplus) && !defined(WITH_LEAN) +} +extern std::ostream &operator<<(std::ostream&, const struct soap_dom_element&); +extern std::istream &operator>>(std::istream&, struct soap_dom_element&); +extern "C" { +#endif + +/******************************************************************************/ + +#ifdef WIN32 +# ifdef SOAP_STD_EXPORTS +# define SOAP_STD_API __declspec(dllexport) +# else +# define SOAP_STD_API +# endif +#else +# define SOAP_STD_API +#endif + +struct SOAP_STD_API soap +{ short state; /* 0 = uninitialized, 1 = initialized, 2 = copy of another soap struct */ + short version; /* 1 = SOAP1.1 and 2 = SOAP1.2 (set automatically from namespace URI in nsmap table) */ + soap_mode mode; + soap_mode imode; + soap_mode omode; + const char *float_format; /* user-definable format string for floats (<1024 chars) */ + const char *double_format; /* user-definable format string for doubles (<1024 chars) */ + const char *dime_id_format; /* user-definable format string for integer DIME id ( 0, gives socket recv timeout in seconds, < 0 in usec */ + int send_timeout; /* when > 0, gives socket send timeout in seconds, < 0 in usec */ + int connect_timeout; /* when > 0, gives socket connect() timeout in seconds, < 0 in usec */ + int accept_timeout; /* when > 0, gives socket accept() timeout in seconds, < 0 in usec */ + int socket_flags; /* socket recv() and send() flags, e.g. set to MSG_NOSIGNAL to disable sigpipe */ + int connect_flags; /* connect() SOL_SOCKET sockopt flags, e.g. set to SO_DEBUG to debug socket */ + int bind_flags; /* bind() SOL_SOCKET sockopt flags, e.g. set to SO_REUSEADDR to enable reuse */ + int accept_flags; /* accept() SOL_SOCKET sockopt flags */ + const struct Namespace *namespaces; /* Pointer to global namespace mapping table */ + struct Namespace *local_namespaces; /* Local namespace mapping table */ + struct soap_nlist *nlist; /* namespace stack */ + struct soap_blist *blist; /* block allocation stack */ + struct soap_clist *clist; /* class instance allocation list */ + void *alist; /* memory allocation (malloc) list */ + struct soap_ilist *iht[SOAP_IDHASH]; + struct soap_plist *pht[SOAP_PTRHASH]; + struct soap_pblk *pblk; /* plist block allocation */ + short pidx; /* plist block allocation */ + struct SOAP_ENV__Header *header; + struct SOAP_ENV__Fault *fault; + int idnum; + void *user; /* to pass user-defined data */ + struct soap_plugin *plugins; /* linked list of plug-in data */ + char *userid; /* HTTP Basic authorization userid */ + char *passwd; /* HTTP Basic authorization passwd */ + int (*fpost)(struct soap*, const char*, const char*, int, const char*, const char*, size_t); + int (*fget)(struct soap*); + int (*fform)(struct soap*); + int (*fposthdr)(struct soap*, const char*, const char*); + int (*fresponse)(struct soap*, int, size_t); + int (*fparse)(struct soap*); + int (*fparsehdr)(struct soap*, const char*, const char*); + int (*fheader)(struct soap*); + int (*fresolve)(struct soap*, const char*, struct in_addr* inaddr); + int (*fconnect)(struct soap*, const char*, const char*, int); + int (*fdisconnect)(struct soap*); + int (*fclosesocket)(struct soap*, SOAP_SOCKET); + int (*fshutdownsocket)(struct soap*, SOAP_SOCKET, int); + SOAP_SOCKET (*fopen)(struct soap*, const char*, const char*, int); + SOAP_SOCKET (*faccept)(struct soap*, SOAP_SOCKET, struct sockaddr*, int *n); + int (*fclose)(struct soap*); + int (*fsend)(struct soap*, const char*, size_t); + size_t (*frecv)(struct soap*, char*, size_t); + int (*fpoll)(struct soap*); + void (*fseterror)(struct soap*, const char **c, const char **s); + int (*fignore)(struct soap*, const char*); + int (*fserveloop)(struct soap*); + void *(*fplugin)(struct soap*, const char*); + void *(*fmalloc)(struct soap*, size_t); +#ifndef WITH_LEANER + int (*fprepareinit)(struct soap*); + int (*fpreparesend)(struct soap*, const char*, size_t); + int (*fpreparerecv)(struct soap*, const char*, size_t); + int (*fpreparefinal)(struct soap*); + void *(*fdimereadopen)(struct soap*, void*, const char*, const char*, const char*); + void *(*fdimewriteopen)(struct soap*, const char*, const char*, const char*); + void (*fdimereadclose)(struct soap*, void*); + void (*fdimewriteclose)(struct soap*, void*); + size_t (*fdimeread)(struct soap*, void*, char*, size_t); + int (*fdimewrite)(struct soap*, void*, const char*, size_t); + void *(*fmimereadopen)(struct soap*, void*, const char*, const char*, const char*); + void *(*fmimewriteopen)(struct soap*, void*, const char*, const char*, const char*, enum soap_mime_encoding); + void (*fmimereadclose)(struct soap*, void*); + void (*fmimewriteclose)(struct soap*, void*); + size_t (*fmimeread)(struct soap*, void*, char*, size_t); + int (*fmimewrite)(struct soap*, void*, const char*, size_t); +#endif + SOAP_SOCKET master; + SOAP_SOCKET socket; +#if defined(__cplusplus) && !defined(WITH_LEAN) + std::ostream *os; + std::istream *is; +#else + void *os; /* preserve alignment */ + void *is; /* preserve alignment */ +#endif +#ifndef UNDER_CE + int sendfd; + int recvfd; +#else + FILE *sendfd; + FILE *recvfd; +#endif + size_t bufidx; /* index in soap.buf[] */ + size_t buflen; /* length of soap.buf[] content */ + soap_wchar ahead; /* parser lookahead */ + short cdata; /* CDATA parser state */ + short body; /* parsed XML element has a body or not */ + unsigned int level; /* XML nesting level */ + size_t count; /* message length counter */ + size_t length; /* message length as set by HTTP header */ + char *labbuf; /* look-aside buffer */ + size_t lablen; /* look-aside buffer allocated length */ + size_t labidx; /* look-aside buffer index to available part */ + char buf[SOAP_BUFLEN];/* send and receive buffer */ + char msgbuf[1024]; /* in/output buffer for messages >=1024 bytes */ + char tmpbuf[1024]; /* in/output buffer for HTTP/MIME headers, simpleType values, attribute names, and DIME must be >=1024 bytes */ + char tag[SOAP_TAGLEN]; + char id[SOAP_TAGLEN]; + char href[SOAP_TAGLEN]; + char type[SOAP_TAGLEN]; + char arrayType[SOAP_TAGLEN]; + char arraySize[SOAP_TAGLEN]; + char arrayOffset[SOAP_TAGLEN]; + short other; + short position; + int positions[SOAP_MAXDIMS]; + short root; + struct soap_attribute *attributes; /* attribute list */ + short encoding; /* when set, output encodingStyle */ + short mustUnderstand; /* a mustUnderstand element was parsed or is output */ + short null; /* parsed XML is xsi:nil */ + short ns; /* when not set, output full xmlns bindings */ + short part; /* parsing state */ + short alloced; + short peeked; + size_t chunksize; + size_t chunkbuflen; + char endpoint[SOAP_TAGLEN]; + char path[SOAP_TAGLEN]; + char host[SOAP_TAGLEN]; + char *action; + char *authrealm; /* HTTP authentication realm */ + char *prolog; /* XML declaration prolog */ + unsigned long ip; /* IP number */ + int port; /* port number */ + short keep_alive; /* connection should be kept open */ + short tcp_keep_alive; /* enable SO_KEEPALIVE */ + unsigned int tcp_keep_idle; /* set TCP_KEEPIDLE */ + unsigned int tcp_keep_intvl; /* set TCP_KEEPINTVL */ + unsigned int tcp_keep_cnt; /* set TCP_KEEPCNT */ + unsigned int max_keep_alive; /* maximum keep-alive session (default=100) */ + const char *proxy_http_version;/* HTTP version of proxy "1.0" or "1.1" */ + const char *proxy_host; /* Proxy Server host name */ + int proxy_port; /* Proxy Server port (default = 8080) */ + const char *proxy_userid; /* Proxy Authorization user name */ + const char *proxy_passwd; /* Proxy Authorization password */ + const char *proxy_from; /* X-Forwarding-For header returned by proxy */ + int status; /* -1 when request, else error code to be returned by server */ + int error; + int errmode; + int errnum; +#ifndef WITH_LEANER + struct soap_dom_element *dom; + struct soap_dime dime; + struct soap_mime mime; + struct soap_xlist *xlist; +#endif +#if !defined(WITH_LEAN) || defined(SOAP_DEBUG) + const char *logfile[SOAP_MAXLOGS]; + FILE *fdebug[SOAP_MAXLOGS]; + struct soap_mlist *mht[SOAP_PTRHASH]; +#endif +#ifndef WITH_LEAN + const char *c14ninclude; + const char *c14nexclude; + struct soap_cookie *cookies; + const char *cookie_domain; + const char *cookie_path; + int cookie_max; +#endif +#ifndef WITH_NOIO +#ifdef WITH_IPV6 + struct sockaddr_storage peer; /* IPv6: set by soap_accept and by UDP recv */ +#else + struct sockaddr_in peer; /* IPv4: set by soap_connect/soap_accept and by UDP recv */ +#endif +#endif + size_t peerlen; +#ifdef WITH_OPENSSL + int (*fsslauth)(struct soap*); + int (*fsslverify)(int, X509_STORE_CTX*); + BIO *bio; + SSL *ssl; + SSL_CTX *ctx; + unsigned short ssl_flags; + const char *keyfile; + const char *password; + const char *dhfile; + const char *cafile; + const char *capath; + const char *crlfile; + const char *randfile; + SSL_SESSION *session; + char session_host[SOAP_TAGLEN]; + int session_port; +#endif +#ifdef WITH_ZLIB + short zlib_state; /* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_INFLATE */ + short zlib_in; /* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_GZIP */ + short zlib_out; /* SOAP_ZLIB_NONE, SOAP_ZLIB_DEFLATE, or SOAP_ZLIB_GZIP */ + z_stream d_stream; /* decompression stream */ + char z_buf[SOAP_BUFLEN]; /* buffer */ + size_t z_buflen; + unsigned short z_level; /* compression level to be used (0=none, 1=fast to 9=best) */ + uLong z_crc; /* internal gzip crc */ + float z_ratio_in; /* detected compression ratio compressed_length/length of inbound message */ + float z_ratio_out; /* detected compression ratio compressed_length/length of outbound message */ +#endif +#ifdef WMW_RPM_IO + void *rpmreqid; +#endif +#ifndef WITH_LEAN +#ifdef __cplusplus + soap(); + soap(soap_mode); + soap(soap_mode, soap_mode); + soap(struct soap&); + ~soap(); +#endif +#endif +}; + +struct soap_code_map +{ long code; + const char *string; +}; + +/* forwarding list */ +struct soap_flist +{ struct soap_flist *next; + int type; + void *ptr; + unsigned int level; + size_t len; + void (*fcopy)(struct soap*, int, int, void*, size_t, const void*, size_t); +}; + +/* id-ref forwarding list */ +struct soap_ilist +{ struct soap_ilist *next; + int type; + size_t size; + void *link; + void *copy; + struct soap_flist *flist; + void *ptr; + unsigned int level; + char id[1]; /* the actual id string value flows into the allocated region below this struct */ +}; + +struct soap_plugin +{ struct soap_plugin *next; + const char *id; + void *data; + int (*fcopy)(struct soap *soap, struct soap_plugin *dst, struct soap_plugin *src); + void (*fdelete)(struct soap *soap, struct soap_plugin *p); /* should delete fields of plugin only and not free(p) */ +}; + +#ifndef WITH_NONAMESPACES +extern SOAP_NMAC struct Namespace namespaces[]; +#endif + +#ifndef WITH_LEAN +# define soap_get0(soap) (((soap)->bufidx>=(soap)->buflen && soap_recv(soap)) ? EOF : (unsigned char)(soap)->buf[(soap)->bufidx]) +# define soap_get1(soap) (((soap)->bufidx>=(soap)->buflen && soap_recv(soap)) ? EOF : (unsigned char)(soap)->buf[(soap)->bufidx++]) +#else +soap_wchar soap_get0(struct soap*); +soap_wchar soap_get1(struct soap*); +#endif + +#define soap_revget1(soap) ((soap)->bufidx--) +#define soap_unget(soap, c) ((soap)->ahead = c) +#define soap_register_plugin(soap, plugin) soap_register_plugin_arg(soap, plugin, NULL) +#define soap_imode(soap, n) ((soap)->mode = (soap)->imode = (n)) +#define soap_set_imode(soap, n) ((soap)->imode |= (n)) +#define soap_clr_imode(soap, n) ((soap)->imode &= ~(n)) +#define soap_omode(soap, n) ((soap)->mode = (soap)->omode = (n)) +#define soap_set_omode(soap, n) ((soap)->omode |= (n)) +#define soap_clr_omode(soap, n) ((soap)->omode &= ~(n)) +#define soap_set_mode(soap, n) ((soap)->imode |= (n), (soap)->omode |= (n)) +#define soap_clr_mode(soap, n) ((soap)->imode &= ~(n), (soap)->omode &= ~(n)) +#define soap_destroy(soap) soap_delete((soap), NULL) + +#ifdef HAVE_STRRCHR +# define soap_strrchr(s, t) strrchr(s, t) +#else + SOAP_FMAC1 char* SOAP_FMAC2 soap_strrchr(const char *s, int t); +#endif + +#ifdef HAVE_STRTOL +# define soap_strtol(s, t, b) strtol(s, t, b) +#else + SOAP_FMAC1 long SOAP_FMAC2 soap_strtol(const char *s, char **t, int b); +#endif + +#ifdef HAVE_STRTOUL +# define soap_strtoul(s, t, b) strtoul(s, t, b) +#else + SOAP_FMAC1 unsigned long SOAP_FMAC2 soap_strtoul(const char *s, char **t, int b); +#endif + +#if defined(WITH_OPENSSL) +# define soap_random soap_rand() +SOAP_FMAC1 int SOAP_FMAC2 soap_rand(void); +#elif defined(HAVE_RANDOM) +# define soap_random (int)random() +#else +# define soap_random rand() +#endif + +#ifdef WITH_NOIDREF +# define soap_embedded(s, p, t) (0) +# define soap_id_lookup(s, i, p, t, n, k) (p) +# define soap_id_forward(s, h, p, len, st, tt, n, k, fc) (p) +# define soap_reference(s, a, t) (1) +# define soap_array_reference(s, p, a, n, t) (1) +# define soap_embed(s, p, a, n, t, pp) (0) +# define soap_embedded_id(s, i, p, t) (i) +# define soap_is_embedded(s, p) (0) +# define soap_is_single(s, p) (1) +# define soap_lookup_type(s, i) (0) +# define soap_getindependent(s) (0) +# define soap_putindependent(s) (0) +# define soap_getelement(s, n) (n) +# define soap_putelement(s, p, t, i, n) (0) +# define soap_markelement(s, p, n) (0) +#endif + +SOAP_FMAC1 void SOAP_FMAC2 soap_header(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_fault(struct soap*); +SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultcode(struct soap*); +SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultsubcode(struct soap*); +SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultstring(struct soap*); +SOAP_FMAC1 const char** SOAP_FMAC2 soap_faultdetail(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_serializeheader(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putheader(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getheader(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_serializefault(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putfault(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getfault(struct soap*); + +SOAP_FMAC1 void SOAP_FMAC2 soap_ssl_init(void); +SOAP_FMAC1 int SOAP_FMAC2 soap_poll(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_connect_command(struct soap*, int, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_connect(struct soap*, const char*, const char*); +SOAP_FMAC1 SOAP_SOCKET SOAP_FMAC2 soap_bind(struct soap*, const char*, int, int); +SOAP_FMAC1 SOAP_SOCKET SOAP_FMAC2 soap_accept(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_accept(struct soap*); +SOAP_FMAC1 const char * SOAP_FMAC2 soap_ssl_error(struct soap*, int); + +SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_server_context(struct soap*, unsigned short, const char*, const char*, const char*, const char*, const char*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_ssl_client_context(struct soap*, unsigned short, const char*, const char*, const char*, const char*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_puthttphdr(struct soap*, int status, size_t count); + +SOAP_FMAC1 const char* SOAP_FMAC2 soap_get_header_attribute(struct soap*, const char*, const char*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_decode_key(char*, size_t, const char*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_decode_val(char*, size_t, const char*); + +SOAP_FMAC1 size_t SOAP_FMAC2 soap_hash(const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_endpoint(struct soap*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_flush_raw(struct soap*, const char*, size_t); +SOAP_FMAC1 int SOAP_FMAC2 soap_flush(struct soap*); +SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_get(struct soap*); +SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_getchar(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_tag_cmp(const char*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_fault(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_sender_fault(struct soap*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_sender_fault_subcode(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_receiver_fault(struct soap*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_receiver_fault_subcode(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_sender_error(struct soap*, const char*, const char*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_receiver_error(struct soap*, const char*, const char*, int); + +SOAP_FMAC1 int SOAP_FMAC2 soap_send_raw(struct soap*, const char*, size_t); +SOAP_FMAC1 int SOAP_FMAC2 soap_recv_raw(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_recv(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_send(struct soap*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_send2(struct soap*, const char*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_send3(struct soap*, const char*, const char*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_pututf8(struct soap*, unsigned long); +SOAP_FMAC1 soap_wchar SOAP_FMAC2 soap_getutf8(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_putbase64(struct soap*, const unsigned char*, int); +SOAP_FMAC1 unsigned char* SOAP_FMAC2 soap_getbase64(struct soap*, int*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_puthex(struct soap*, const unsigned char*, int); +SOAP_FMAC1 unsigned char* SOAP_FMAC2 soap_gethex(struct soap*, int*); + +#ifndef WITH_LEANER +SOAP_FMAC1 int SOAP_FMAC2 soap_xop_forward(struct soap*, unsigned char**, int*, char**, char**, char**); +SOAP_FMAC1 int SOAP_FMAC2 soap_dime_forward(struct soap*, unsigned char**, int*, char**, char**, char**); +#endif + +#ifndef WITH_NOIDREF +SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_lookup_id(struct soap*, void *p, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_lookup(struct soap*, const void *p, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_pointer_enter(struct soap*, const void *p, const struct soap_array *a, int n, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_array_pointer_lookup(struct soap*, const void *p, const struct soap_array *a, int n, int t, struct soap_plist**); +SOAP_FMAC1 int SOAP_FMAC2 soap_embed(struct soap *soap, const void *p, const struct soap_array *a, int n, const char *tag, int type); +SOAP_FMAC1 struct soap_ilist* SOAP_FMAC2 soap_lookup(struct soap*, const char*); +SOAP_FMAC1 struct soap_ilist* SOAP_FMAC2 soap_enter(struct soap*, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_resolve(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_embedded(struct soap*, const void *p, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_reference(struct soap*, const void *p, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_array_reference(struct soap*, const void *p, const struct soap_array *a, int n, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_embedded_id(struct soap*, int id, const void *p, int t); +SOAP_FMAC1 int SOAP_FMAC2 soap_is_embedded(struct soap*, struct soap_plist*); +SOAP_FMAC1 int SOAP_FMAC2 soap_is_single(struct soap*, struct soap_plist*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_embedded(struct soap*, struct soap_plist*); +#endif + +SOAP_FMAC1 int SOAP_FMAC2 soap_begin_count(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_end_count(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_begin_send(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_end_send(struct soap*); + +SOAP_FMAC1 const struct soap_code_map* SOAP_FMAC2 soap_code(const struct soap_code_map*, const char*); +SOAP_FMAC1 long SOAP_FMAC2 soap_code_int(const struct soap_code_map*, const char*, long); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_code_str(const struct soap_code_map*, long); +SOAP_FMAC1 long SOAP_FMAC2 soap_code_bits(const struct soap_code_map*, const char*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_code_list(struct soap*, const struct soap_code_map*, long); + +SOAP_FMAC1 int SOAP_FMAC2 soap_getline(struct soap*, char*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_begin_recv(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_end_recv(struct soap*); + +SOAP_FMAC1 void* SOAP_FMAC2 soap_malloc(struct soap*, size_t); +SOAP_FMAC1 void SOAP_FMAC2 soap_dealloc(struct soap*, void*); +SOAP_FMAC1 struct soap_clist * SOAP_FMAC2 soap_link(struct soap*, void*, int, int, int (*fdelete)(struct soap_clist*)); +SOAP_FMAC1 void SOAP_FMAC2 soap_unlink(struct soap*, const void*); +SOAP_FMAC1 void SOAP_FMAC2 soap_free_temp(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_del(struct soap*); + +SOAP_FMAC1 void* SOAP_FMAC2 soap_track_malloc(struct soap*, const char*, int, size_t); +SOAP_FMAC1 void SOAP_FMAC2 soap_track_free(struct soap*, const char*, int, void*); + +#ifndef WITH_NOIDREF +SOAP_FMAC1 int SOAP_FMAC2 soap_lookup_type(struct soap*, const char *id); +SOAP_FMAC1 void* SOAP_FMAC2 soap_id_lookup(struct soap*, const char *id, void **p, int t, size_t n, unsigned int k); +SOAP_FMAC1 void* SOAP_FMAC2 soap_id_forward(struct soap*, const char *id, void *p, size_t len, int st, int tt, size_t n, unsigned int k, void(*fcopy)(struct soap*, int, int, void*, size_t, const void*, size_t)); +#endif +SOAP_FMAC1 void* SOAP_FMAC2 soap_id_enter(struct soap*, const char *id, void *p, int t, size_t n, unsigned int k, const char *type, const char *arrayType, void *(*finstantiate)(struct soap*, int, const char*, const char*, size_t*)); +SOAP_FMAC1 void SOAP_FMAC2 soap_fcopy(struct soap *soap, int st, int tt, void *p, size_t, const void *q, size_t n); + +SOAP_FMAC1 int SOAP_FMAC2 soap_size(const int *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_getoffsets(const char *, const int *, int *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_getsize(const char *, const char *, int *); +SOAP_FMAC1 int SOAP_FMAC2 soap_getsizes(const char *, int *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_getposition(const char *, int *); + +SOAP_FMAC1 char* SOAP_FMAC2 soap_putsize(struct soap*, const char *, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_putsizesoffsets(struct soap*, const char *, const int *, const int *, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_putsizes(struct soap*, const char *, const int *, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_putoffset(struct soap*, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_putoffsets(struct soap*, const int *, int); + +SOAP_FMAC1 int SOAP_FMAC2 soap_closesock(struct soap*); + +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_new(void); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_new1(soap_mode); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_new2(soap_mode, soap_mode); +SOAP_FMAC1 void SOAP_FMAC2 soap_free(struct soap*); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_copy(struct soap*); +SOAP_FMAC1 struct soap *SOAP_FMAC2 soap_copy_context(struct soap*, struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_copy_stream(struct soap*, struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_init(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_init1(struct soap*, soap_mode); +SOAP_FMAC1 void SOAP_FMAC2 soap_init2(struct soap*, soap_mode, soap_mode); +SOAP_FMAC1 void SOAP_FMAC2 soap_done(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_cleanup(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_begin(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_end(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_delete(struct soap*, void*); + +#ifdef SOAP_DEBUG +SOAP_FMAC1 void SOAP_FMAC2 soap_set_recv_logfile(struct soap*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_sent_logfile(struct soap*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_test_logfile(struct soap*, const char*); +SOAP_FMAC1 void SOAP_FMAC2 soap_close_logfiles(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_open_logfile(struct soap*, int); +#endif + +SOAP_FMAC1 const char* SOAP_FMAC2 soap_value(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_match_tag(struct soap*, const char*, const char *); +SOAP_FMAC1 int SOAP_FMAC2 soap_match_array(struct soap*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_element(struct soap*, const char*, int, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_begin_out(struct soap*, const char *tag, int id, const char *type); +SOAP_FMAC1 int SOAP_FMAC2 soap_array_begin_out(struct soap*, const char *tag, int id, const char *type, const char *offset); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_ref(struct soap*, const char *tag, int id, int href); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_href(struct soap*, const char *tag, int id, const char *ref, const char *val); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_null(struct soap*, const char *tag, int id, const char *type); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_id(struct soap*, const char *tag, int id, const void *p, const struct soap_array *a, int d, const char *type, int n); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_result(struct soap*, const char *tag); +SOAP_FMAC1 void SOAP_FMAC2 soap_check_result(struct soap*, const char *tag); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_end_out(struct soap*, const char *tag); +SOAP_FMAC1 int SOAP_FMAC2 soap_element_start_end_out(struct soap*, const char *tag); + +SOAP_FMAC1 int SOAP_FMAC2 soap_attribute(struct soap*, const char*, const char*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_element_begin_in(struct soap*, const char *tag, int nillable, const char *type); + +SOAP_FMAC1 int SOAP_FMAC2 soap_element_end_in(struct soap*, const char *tag); + +SOAP_FMAC1 int SOAP_FMAC2 soap_peek_element(struct soap*); + +SOAP_FMAC1 void SOAP_FMAC2 soap_retry(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_revert(struct soap*); + +SOAP_FMAC1 char* SOAP_FMAC2 soap_strdup(struct soap*, const char*); +SOAP_FMAC1 const char * SOAP_FMAC2 soap_strsearch(const char *big, const char *little); + +SOAP_FMAC1 int SOAP_FMAC2 soap_string_out(struct soap*, const char *s, int flag); +SOAP_FMAC1 char* SOAP_FMAC2 soap_string_in(struct soap*, int, long, long); + +#ifndef WITH_LEANER +SOAP_FMAC1 int SOAP_FMAC2 soap_wstring_out(struct soap*, const wchar_t *s, int flag); +SOAP_FMAC1 wchar_t* SOAP_FMAC2 soap_wstring_in(struct soap*, int, long, long); +#endif + +SOAP_FMAC1 int SOAP_FMAC2 soap_match_namespace(struct soap*, const char *, const char*, size_t n1, size_t n2); + +SOAP_FMAC1 int SOAP_FMAC2 soap_set_namespaces(struct soap*, const struct Namespace*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_local_namespaces(struct soap*); + +SOAP_FMAC1 void SOAP_FMAC2 soap_pop_namespace(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_push_namespace(struct soap*, const char *,const char *); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_current_namespace(struct soap *soap, const char *tag); + +SOAP_FMAC1 struct soap_nlist* SOAP_FMAC2 soap_lookup_ns(struct soap *soap, const char *tag, size_t n); + +SOAP_FMAC1 int SOAP_FMAC2 soap_store_lab(struct soap*, const char*, size_t); +SOAP_FMAC1 int SOAP_FMAC2 soap_append_lab(struct soap*, const char*, size_t); + +SOAP_FMAC1 int SOAP_FMAC2 soap_new_block(struct soap*); +SOAP_FMAC1 void* SOAP_FMAC2 soap_push_block(struct soap*, size_t); +SOAP_FMAC1 void SOAP_FMAC2 soap_pop_block(struct soap*); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_size_block(struct soap*, size_t); +SOAP_FMAC1 char* SOAP_FMAC2 soap_first_block(struct soap*); +SOAP_FMAC1 char* SOAP_FMAC2 soap_next_block(struct soap*); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_block_size(struct soap*); +SOAP_FMAC1 char* SOAP_FMAC2 soap_save_block(struct soap*, char*, int); +SOAP_FMAC1 void SOAP_FMAC2 soap_end_block(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_begin_out(struct soap*); +SOAP_FMAC1 int soap_envelope_end_out(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_begin_in(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_envelope_end_in(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_body_begin_out(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_body_end_out(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_body_begin_in(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_body_end_in(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_recv_header(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_response(struct soap*, int); + +SOAP_FMAC1 int SOAP_FMAC2 soap_send_empty_response(struct soap*, int status); +SOAP_FMAC1 int SOAP_FMAC2 soap_recv_empty_response(struct soap*); + +SOAP_FMAC1 int SOAP_FMAC2 soap_send_fault(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_recv_fault(struct soap*); + +#ifndef WITH_NOSTDLIB +SOAP_FMAC1 void SOAP_FMAC2 soap_print_fault(struct soap*, FILE*); +SOAP_FMAC1 char* SOAP_FMAC2 soap_sprint_fault(struct soap*, char*, size_t); +SOAP_FMAC1 void SOAP_FMAC2 soap_print_fault_location(struct soap*, FILE*); +#endif + +SOAP_FMAC1 int SOAP_FMAC2 soap_s2byte(struct soap*, const char*, char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2short(struct soap*, const char*, short*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2int(struct soap*, const char*, int*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2long(struct soap*, const char*, long*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2LONG64(struct soap*, const char*, LONG64*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2float(struct soap*, const char*, float*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2double(struct soap*, const char*, double*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedByte(struct soap*, const char*, unsigned char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedShort(struct soap*, const char*, unsigned short*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedInt(struct soap*, const char*, unsigned int*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2unsignedLong(struct soap*, const char*, unsigned long*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2ULONG64(struct soap*, const char*, ULONG64*); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2string(struct soap*, const char*, char**); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2QName(struct soap*, const char*, char**); + +#ifndef WITH_LEAN +SOAP_FMAC1 int SOAP_FMAC2 soap_s2wchar(struct soap*, const char*, wchar_t**); +SOAP_FMAC1 int SOAP_FMAC2 soap_s2dateTime(struct soap*, const char*, time_t*); +SOAP_FMAC1 char* SOAP_FMAC2 soap_s2base64(struct soap*, const unsigned char*, char*, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_s2hex(struct soap*, const unsigned char*, char*, int); +#endif + +SOAP_FMAC1 const char* SOAP_FMAC2 soap_byte2s(struct soap*, char); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_short2s(struct soap*, short); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_int2s(struct soap*, int); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_long2s(struct soap*, long); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_LONG642s(struct soap*, LONG64); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_float2s(struct soap*, float); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_double2s(struct soap*, double); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedByte2s(struct soap*, unsigned char); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedShort2s(struct soap*, unsigned short); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedInt2s(struct soap*, unsigned int); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_unsignedLong2s(struct soap*, unsigned long); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_ULONG642s(struct soap*, ULONG64); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_QName2s(struct soap*, const char*); + +#ifndef WITH_LEAN +SOAP_FMAC1 const char* SOAP_FMAC2 soap_wchar2s(struct soap*, const wchar_t*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_dateTime2s(struct soap*, time_t); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_base642s(struct soap*, const char*, char*, size_t, int*); +SOAP_FMAC1 const char* SOAP_FMAC2 soap_hex2s(struct soap*, const char*, char*, size_t, int*); +#endif + + +SOAP_FMAC1 int* SOAP_FMAC2 soap_inint(struct soap*, const char *tag, int *p, const char *, int); +SOAP_FMAC1 char* SOAP_FMAC2 soap_inbyte(struct soap*, const char *tag, char *p, const char *, int); +SOAP_FMAC1 long* SOAP_FMAC2 soap_inlong(struct soap*, const char *tag, long *p, const char *, int); +SOAP_FMAC1 LONG64* SOAP_FMAC2 soap_inLONG64(struct soap*, const char *tag, LONG64 *p, const char *, int); +SOAP_FMAC1 short* SOAP_FMAC2 soap_inshort(struct soap*, const char *tag, short *p, const char *, int); +SOAP_FMAC1 float* SOAP_FMAC2 soap_infloat(struct soap*, const char *tag, float *p, const char *, int); +SOAP_FMAC1 double* SOAP_FMAC2 soap_indouble(struct soap*, const char *tag, double *p, const char *, int); +SOAP_FMAC1 unsigned char* SOAP_FMAC2 soap_inunsignedByte(struct soap*, const char *tag, unsigned char *p, const char *, int); +SOAP_FMAC1 unsigned short* SOAP_FMAC2 soap_inunsignedShort(struct soap*, const char *tag, unsigned short *p, const char *, int); +SOAP_FMAC1 unsigned int* SOAP_FMAC2 soap_inunsignedInt(struct soap*, const char *tag, unsigned int *p, const char *, int); +SOAP_FMAC1 unsigned long* SOAP_FMAC2 soap_inunsignedLong(struct soap*, const char *tag, unsigned long *p, const char *, int); +SOAP_FMAC1 ULONG64* SOAP_FMAC2 soap_inULONG64(struct soap*, const char *tag, ULONG64 *p, const char *, int); +SOAP_FMAC1 char** SOAP_FMAC2 soap_instring(struct soap*, const char *tag, char **p, const char *, int, int, long, long); +SOAP_FMAC1 char** SOAP_FMAC2 soap_inliteral(struct soap*, const char *tag, char **p); + +#ifndef WITH_LEAN +SOAP_FMAC1 time_t* SOAP_FMAC2 soap_indateTime(struct soap*, const char *tag, time_t *p, const char *, int); +SOAP_FMAC1 time_t SOAP_FMAC2 soap_timegm(struct tm*); +#endif + +#ifndef WITH_LEANER +SOAP_FMAC1 wchar_t** SOAP_FMAC2 soap_inwstring(struct soap*, const char *tag, wchar_t **p, const char *, int, long, long); +SOAP_FMAC1 wchar_t** SOAP_FMAC2 soap_inwliteral(struct soap*, const char *tag, wchar_t **p); +#endif + +SOAP_FMAC1 int SOAP_FMAC2 soap_outbyte(struct soap*, const char *tag, int id, const char *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outshort(struct soap*, const char *tag, int id, const short *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outint(struct soap*, const char *tag, int id, const int *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outlong(struct soap*, const char *tag, int id, const long *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outLONG64(struct soap*, const char *tag, int id, const LONG64 *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outfloat(struct soap*, const char *tag, int id, const float *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outdouble(struct soap*, const char *tag, int id, const double *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedByte(struct soap*, const char *tag, int id, const unsigned char *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedShort(struct soap*, const char *tag, int id, const unsigned short *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedInt(struct soap*, const char *tag, int id, const unsigned int *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outunsignedLong(struct soap*, const char *tag, int id, const unsigned long *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outULONG64(struct soap*, const char *tag, int id, const ULONG64 *p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outstring(struct soap*, const char *tag, int id, char *const*p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outliteral(struct soap*, const char *tag, char *const*p, const char *type); + +#ifndef WITH_LEAN +SOAP_FMAC1 int SOAP_FMAC2 soap_outdateTime(struct soap*, const char *tag, int id, const time_t *p, const char *, int); +#endif + +#ifndef WITH_LEANER +SOAP_FMAC1 int SOAP_FMAC2 soap_outwstring(struct soap*, const char *tag, int id, wchar_t *const*p, const char *, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_outwliteral(struct soap*, const char *tag, wchar_t *const*p, const char *type); +#endif + +#ifndef WITH_LEANER +SOAP_FMAC1 int SOAP_FMAC2 soap_attachment(struct soap *, const char*, int, const void*, const struct soap_array*, const char*, const char*, const char*, int, const char*, int); +SOAP_FMAC1 int SOAP_FMAC2 soap_move(struct soap*, long); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_tell(struct soap*); +SOAP_FMAC1 char* SOAP_FMAC2 soap_dime_option(struct soap*, unsigned short, const char*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getdimehdr(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getdime(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putdimehdr(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putdime(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getmimehdr(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_getmime(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putmimehdr(struct soap*, struct soap_multipart*); +SOAP_FMAC1 int SOAP_FMAC2 soap_putmime(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_dime(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_set_mime(struct soap*, const char *boundary, const char *start); +SOAP_FMAC1 void SOAP_FMAC2 soap_clr_dime(struct soap*); +SOAP_FMAC1 void SOAP_FMAC2 soap_clr_mime(struct soap*); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_dime_attachment(struct soap*, char *ptr, size_t size, const char *type, const char *id, unsigned short optype, const char *option); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_mime_attachment(struct soap*, char *ptr, size_t size, enum soap_mime_encoding encoding, const char *type, const char *id, const char *location, const char *description); +SOAP_FMAC1 void SOAP_FMAC2 soap_post_check_mime_attachments(struct soap *soap); +SOAP_FMAC1 int SOAP_FMAC2 soap_check_mime_attachments(struct soap *soap); +SOAP_FMAC1 struct soap_multipart* SOAP_FMAC2 soap_get_mime_attachment(struct soap *soap, void *handle); +SOAP_FMAC1 struct soap_multipart* SOAP_FMAC2 soap_next_multipart(struct soap_multipart*); +SOAP_FMAC1 int SOAP_FMAC2 soap_match_cid(struct soap*, const char*, const char*); +#endif + +SOAP_FMAC1 int SOAP_FMAC2 soap_register_plugin_arg(struct soap*, int (*fcreate)(struct soap*, struct soap_plugin*, void*), void*); +SOAP_FMAC1 void* SOAP_FMAC2 soap_lookup_plugin(struct soap*, const char*); + +SOAP_FMAC1 const char* SOAP_FMAC2 soap_attr_value(struct soap *soap, const char *name, int flag); +SOAP_FMAC1 int SOAP_FMAC2 soap_set_attr(struct soap *soap, const char *name, const char *value); +SOAP_FMAC1 void SOAP_FMAC2 soap_clr_attr(struct soap *soap); + +#ifdef WITH_COOKIES +SOAP_FMAC1 void SOAP_FMAC2 soap_getcookies(struct soap *soap, const char *val); +SOAP_FMAC1 size_t SOAP_FMAC2 soap_encode_cookie(const char*, char*, size_t); +SOAP_FMAC1 extern struct soap_cookie* SOAP_FMAC2 soap_set_cookie(struct soap*, const char*, const char*, const char*, const char*); +SOAP_FMAC1 extern struct soap_cookie* SOAP_FMAC2 soap_cookie(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern char* SOAP_FMAC2 soap_cookie_value(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern char* SOAP_FMAC2 soap_env_cookie_value(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern time_t SOAP_FMAC2 soap_cookie_expire(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern int SOAP_FMAC2 soap_set_cookie_expire(struct soap*, const char*, long, const char*, const char*); +SOAP_FMAC1 extern int SOAP_FMAC2 soap_set_cookie_session(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern int SOAP_FMAC2 soap_clr_cookie_session(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern void SOAP_FMAC2 soap_clr_cookie(struct soap*, const char*, const char*, const char*); +SOAP_FMAC1 extern int SOAP_FMAC2 soap_getenv_cookies(struct soap*); +SOAP_FMAC1 extern struct soap_cookie* SOAP_FMAC2 soap_copy_cookies(struct soap*, struct soap*); +SOAP_FMAC1 extern void SOAP_FMAC2 soap_free_cookies(struct soap*); +#endif + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif diff --git a/org.glite.lbjp-common.gsoap-plugin/test/test_gsplugin_cxx.cpp b/org.glite.lbjp-common.gsoap-plugin/test/test_gsplugin_cxx.cpp new file mode 100644 index 0000000..27593ae --- /dev/null +++ b/org.glite.lbjp-common.gsoap-plugin/test/test_gsplugin_cxx.cpp @@ -0,0 +1,63 @@ +/* +Copyright (c) Members of the EGEE Collaboration. 2004-2010. +See http://www.eu-egee.org/partners for details on the copyright holders. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include + +#include "stdsoap2.h" +#include "glite_gsplugin.h" + +#define TEST_STR "123456789ABCDEF" + +int main() { + struct soap *mydlo = NULL; + glite_gsplugin_Context gsplugin_ctx = NULL; + int ok1, ok2; + + // test 1 - stdsoap2.c compatibility + if ((mydlo = soap_new()) == NULL) { + std::cerr << "Couldn't create soap" << std::endl; + return 1; + } + soap_set_endpoint(mydlo, TEST_STR); + std::cout << mydlo->endpoint << std::endl; + ok1 = strcmp(mydlo->endpoint, TEST_STR); + + // test 2 - glite_gsplugin.c compatibility + // + // not real test, just may crash in bad test case on calling + // soap->fdelete where will be other function + if ( glite_gsplugin_init_context(&gsplugin_ctx) ) { + std::cerr << "Couldn't create gSOAP plugin context" << std::endl; + goto err; + } + if (soap_register_plugin_arg(mydlo, glite_gsplugin, gsplugin_ctx)) { + std::cerr << "Couldn't register gSoap plugin" << std::endl; + goto err; + } + + soap_done(mydlo); + free(mydlo); + glite_gsplugin_free_context(gsplugin_ctx); + return ok1 && ok2; + +err: + if (gsplugin_ctx) glite_gsplugin_free_context(gsplugin_ctx); + if (mydlo) soap_destroy(mydlo); + return 1; +} + +Namespace namespaces[] = {{NULL, NULL, NULL, NULL}}; diff --git a/org.glite.lbjp-common.gss/LICENSE b/org.glite.lbjp-common.gss/LICENSE new file mode 100644 index 0000000..259a91f --- /dev/null +++ b/org.glite.lbjp-common.gss/LICENSE @@ -0,0 +1,69 @@ +LICENSE file for EGEE Middleware +================================ + +Copyright (c) 2004 on behalf of the EU EGEE Project: +The European Organization for Nuclear Research (CERN), +Istituto Nazionale di Fisica Nucleare (INFN), Italy +Datamat Spa, Italy +Centre National de la Recherche Scientifique (CNRS), France +CS Systeme d'Information (CSSI), France +Royal Institute of Technology, Center for Parallel Computers (KTH-PDC), Sweden +Universiteit van Amsterdam (UvA), Netherlands +University of Helsinki (UH.HIP), Finlan +University of Bergen (UiB), Norway +Council for the Central Laboratory of the Research Councils (CCLRC), United Kingdom + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +3. The end-user documentation included with the redistribution, if +any, must include the following acknowledgment: "This product includes +software developed by The EU EGEE Project (http://cern.ch/eu-egee/)." +Alternatively, this acknowledgment may appear in the software itself, if +and wherever such third-party acknowledgments normally appear. + +4. The names EGEE and the EU EGEE Project must not be +used to endorse or promote products derived from this software without +prior written permission. For written permission, please contact +. + +5. You are under no obligation whatsoever to provide anyone with any +bug fixes, patches, or upgrades to the features, functionality or +performance of the Software ("Enhancements") that you may develop over +time; however, if you choose to provide your Enhancements to The EU +EGEE Project, or if you choose to otherwise publish or distribute your +Enhancements, in source code form without contemporaneously requiring +end users of The EU EGEE Proejct to enter into a separate written license +agreement for such Enhancements, then you hereby grant The EU EGEE Project +a non-exclusive, royalty-free perpetual license to install, use, copy, +modify, prepare derivative works, incorporate into the EGEE Middleware +or any other computer software, distribute, and sublicense your +Enhancements or derivative works thereof, in binary and source code +form (if any), whether developed by The EU EGEE Project or third parties. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL PROJECT OR ITS CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +This software consists of voluntary contributions made by many +individuals on behalf of the EU EGEE Prject. For more information on The +EU EGEE Project, please see http://cern.ch/eu-egee/. For more information on +EGEE Middleware, please see http://egee-jra1.web.cern.ch/egee-jra1/ + + diff --git a/org.glite.lbjp-common.gss/Makefile b/org.glite.lbjp-common.gss/Makefile new file mode 100644 index 0000000..dc8b50b --- /dev/null +++ b/org.glite.lbjp-common.gss/Makefile @@ -0,0 +1,153 @@ +# defaults +top_srcdir=.. +builddir=build +top_builddir=${top_srcdir}/${builddir} +stagedir=. +globalprefix=glite +package=gss +version=1.0.0 +PREFIX=/opt/glite + +glite_location=/opt/glite +globus_prefix=/opt/globus +cppunit_prefix=/opt/cppunit +nothrflavour=gcc32 +thrflavour=gcc32pthr + +CC=gcc + +-include Makefile.inc +-include ../project/version.properties + +version=${module.version} + +# In order to use libtool versioning correcty, we must have: +# +# current = major + minor + offset +# revision = patch +# age = minor +# +# where offset is a sum of maximal released minor's of all previous major's +# + +# counted minors: gsoap-plugin 1.5 +# TODO: bump offset to 5 on next major change +offset=-1 +version_info:=-version-info ${shell \ + perl -e '$$,=":"; @F=split "\\.","${version}"; print $$F[0]+$$F[1]+${offset},$$F[2],$$F[1]' } + +VPATH=${top_srcdir}/src:${top_srcdir}/test + +TEST_LIBS:=-L${cppunit_prefix}/${libdir} -lcppunit +TEST_INC:=-I${cppunit_prefix}/include + +default: all + +DEBUG:=-g -O0 -W -Wall -Wno-unused-parameter +# not for globus, gsoap: -Werror + +CFLAGS:= ${DEBUG} \ + -DVERSION=\"${version}\" \ + -I. -I${top_srcdir}/interface \ + -I${stagedir}/include \ + ${COVERAGE_FLAGS} -D_GNU_SOURCE -DDATAGRID_EXTENSION + +LDFLAGS:=${COVERAGE_FLAGS} + +COMPILE:=libtool --mode=compile ${CC} ${CFLAGS} +LINK:=libtool --mode=link ${CC} -rpath ${stagedir}/${libdir} ${LDFLAGS} +LINKXX:=libtool --mode=link ${CXX} -rpath ${stagedir}/${libdir} ${LDFLAGS} +INSTALL:=libtool --mode=install install + +GLOBUS_INC:= -I${globus_prefix}/include/${nothrflavour} +GLOBUS_THR_INC:= -I${globus_prefix}/include/${thrflavour} + +GLOBUS_LIBS:= -L${globus_prefix}/lib \ + -lglobus_common_${nothrflavour} \ + -lglobus_gssapi_gsi_${nothrflavour} \ + +GLOBUS_THR_LIBS:= -L${globus_prefix}/lib \ + -lglobus_common_${thrflavour} \ + -lglobus_gssapi_gsi_${thrflavour} + +ARES_INC:=-I${cares_prefix}/include +ARES_LIBS:=-L${cares_prefix}/${libdir} -L${cares_prefix}/lib -lcares + +EX_LIBS:= ${GLOBUS_LIBS} ${ARES_LIBS} +EX_THRLIBS := ${GLOBUS_THR_LIBS} ${ARES_LIBS} + +HDRS:=glite_gss.h + +GSS_OBJS:=glite_gss.o +GSS_LOBJS:=${GSS_OBJS:.o=.lo} +GSS_THROBJS:=${GSS_OBJS:.o=.thr.o} +GSS_THRLOBJS:=${GSS_OBJS:.o=.thr.lo} + +GSS_STATICLIB:=libglite_security_gss_${nothrflavour}.a +GSS_THRSTATICLIB:=libglite_security_gss_${thrflavour}.a +GSS_LTLIB:=libglite_security_gss_${nothrflavour}.la +GSS_THRLTLIB:=libglite_security_gss_${thrflavour}.la + +${GSS_STATICLIB}: ${GSS_OBJS} + ar crv $@ ${GSS_OBJS} + ranlib $@ + +${GSS_THRSTATICLIB}: ${GSS_THROBJS} + ar crv $@ ${GSS_THROBJS} + ranlib $@ + +${GSS_LTLIB}: ${GSS_OBJS} + ${LINK} ${version_info} -o $@ ${GSS_LOBJS} ${EX_LIBS} + +${GSS_THRLTLIB}: ${GSS_THROBJS} + ${LINK} ${version_info} -o $@ ${GSS_THRLOBJS} ${EX_THRLIBS} + + +all compile: \ + ${GSS_STATICLIB} ${GSS_LTLIB} ${GSS_THRSTATICLIB} ${GSS_THRLTLIB} \ + examples + +check: compile check.gss + +check.gss: test_gss + # ./test_gss out.xml + echo test_gss not run automatically util we have got some credentials in X509_USER_PROXY + +test_gss: test_gss.o + ${LINKXX} -o $@ test_gss.o ${GSS_LTLIB} ${TEST_LIBS} ${GLOBUS_LIBS} ${EX_LIBS} + +test_coverage: + -mkdir coverage + cd coverage && $(MAKE) -f ../Makefile top_srcdir=../../ COVERAGE_FLAGS="-fprofile-arcs -ftest-coverage" check + cd coverage && for i in ${OBJS}; do gcov -o .libs/ $$i ; done + +examples: + +doc: + +stage: + $(MAKE) install PREFIX=${stagedir} DOSTAGE=yes + +install: + -mkdir -p ${PREFIX}/${libdir} + -mkdir -p ${PREFIX}/share/doc/${package}-${version} + -mkdir -p ${PREFIX}/include/glite/security + ${INSTALL} -m 755 ${GSS_LTLIB} ${GSS_THRLTLIB} ${PREFIX}/${libdir} + ${INSTALL} -m 644 ${top_srcdir}/LICENSE ${PREFIX}/share/doc/${package}-${version} + cd ${top_srcdir}/interface && ${INSTALL} -m 644 ${HDRS} ${PREFIX}/include/glite/security/ + if [ x${DOSTAGE} = xyes ]; then \ + install -m 644 ${GSS_STATICLIB} ${GSS_THRSTATICLIB} ${PREFIX}/${libdir}; \ + fi + +clean: + rm -rf *.o *.lo *.a *.la .libs test_gss + rm -rvf log.xml project/ rpmbuild/ RPMS/ tgz/ debian/ + +%.o: %.c + ${COMPILE} ${GLOBUS_INC} ${ARES_INC} -o $@ -c $< + +%.thr.o: %.c + ${COMPILE} ${GLOBUS_THR_INC} ${ARES_INC} -o $@ -c $< + +test_gss.o: %.o: %.cpp + ${CXX} -c ${CFLAGS} ${GLOBUS_INC} ${TEST_INC} -Wno-error $< diff --git a/org.glite.lbjp-common.gss/configure b/org.glite.lbjp-common.gss/configure new file mode 100755 index 0000000..d02462c --- /dev/null +++ b/org.glite.lbjp-common.gss/configure @@ -0,0 +1,927 @@ +#!/usr/bin/perl + +# WARNING: Don't edit this file unless it is the master copy in org.glite.lb +# +# For the purpose of standalone builds of lb/jobid/lbjp-common components +# it is copied on tagging + +# $Header$ +# +# Copyright (c) Members of the EGEE Collaboration. 2004-2010. +# See http://www.eu-egee.org/partners/ for details on the copyright holders. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +use Getopt::Long; + +my $pwd = `pwd`; chomp $pwd; +my $prefix = $pwd.'/stage'; +my $stagedir; +my $staged; +my $module; +my $thrflavour = 'gcc64dbgpthr'; +my $nothrflavour = 'gcc64dbg'; +my $mode = 'build'; +my $help = 0; +my $listmodules; +my $version; +my $branch; +my $output; +my $lb_tag = ''; +my $lbjp_tag = ''; +my $jp_tag = ''; +my $sec_tag = ''; +my $jobid_tag = ''; +my $libdir = getlibdir(); + +my @nodes = qw/client server logger utils client-java doc ws-test db jpprimary jpindex jpclient harvester/; +my %enable_nodes; +my %disable_nodes; + +my %extern_prefix = ( + cares => '/opt/c-ares', + classads => '/opt/classads', + cppunit => '/usr', + expat => '/usr', + globus => '/opt/globus', + gsoap => '/usr', + mysql => '/usr', + 'mysql-devel' => '', + 'mysql-server' => '', + voms => '/opt/glite', + gridsite => '/opt/glite', + lcas => '/opt/glite', + trustmanager => '/opt/glite', + utiljava => '/opt/glite', + ant => '/usr', + jdk => '/usr', + libtar => '/usr', + axis => '/usr', + log4c => '/usr', + postgresql => '/usr' +); + +my %jar = ( + 'commons-codec' => '/usr/share/java/commons-codec.jar', + 'commons-lang' => '/usr/share/java/commons-lang.jar', +); + + +my %glite_prefix; +my %need_externs; +my %need_externs_type; +my %need_jars; +my %extrafull; +my %extranodmod; +my %deps; +my %deps_type; +my %buildroot; + +my %lbmodules = ( + 'lb' => [ qw/client client-java common doc logger server state-machine types utils ws-interface ws-test harvester yaim glite-LB/], + 'security' => [qw/gss gsoap-plugin/], + 'lbjp-common' => [qw/db log maildir server-bones trio jp-interface/], + 'jobid' => [qw/api-c api-cpp api-java/], + 'jp' => [ qw/client doc index primary server-common ws-interface/ ], + 'gridsite' => [ qw/apache shared commands core/ ], + ); + + +my @opts = ( + 'prefix=s' => \$prefix, + 'staged=s' => \$staged, + 'module=s' => \$module, + 'thrflavour=s' => \$thrflavour, + 'nothrflavour=s' => \$nothrflavour, + 'mode=s' => \$mode, + 'listmodules=s' => \$listmodules, + 'version=s' => \$version, + 'branch=s' => \$branch, + 'output=s' => \$output, + 'stage=s' => \$stagedir, + 'lb-tag=s' => \$lb_tag, + 'lbjp-common-tag=s' => \$lbjp_tag, + 'jp-tag=s' => \$jp_tag, + 'security-tag=s' => \$sec_tag, + 'jobid-tag=s' => \$jobid_tag, + 'help' => \$help, + 'libdir=s' => \$libdir, +); + +for (@nodes) { + $enable_nodes{$_} = 0; + $disable_nodes{$_} = 0; + + push @opts,"disable-$_",\$disable_nodes{$_}; + push @opts,"enable-$_",\$enable_nodes{$_}; +} + +push @opts,"with-$_=s",\$extern_prefix{$_} for keys %extern_prefix; +push @opts,"with-$_=s",\$jar{$_} for keys %jar; + +my @keeparg = @ARGV; + +GetOptions @opts or die "Errors parsing command line\n"; + +$extern_prefix{'mysql-devel'}=$extern_prefix{mysql} if $extern_prefix{'mysql-devel'} eq ''; +$extern_prefix{'mysql-server'}=$extern_prefix{mysql} if $extern_prefix{'mysql-server'} eq ''; + +if ($help) { usage(); exit 0; } + +if ($listmodules) { + my @m = map "org.glite.$listmodules.$_",@{$lbmodules{$listmodules}}; + print "@m\n"; + exit 0; +} + +warn "$0: --version, --branch and --output make sense only in --mode=etics\n" + if ($version || $output || $branch) && $mode ne 'etics'; + +my $en; +for (keys %enable_nodes) { $en = 1 if $enable_nodes{$_}; } + +my $dis; +for (keys %disable_nodes) { $dis = 1 if $disable_nodes{$_}; } + +die "--enable-* and --disable-* are mutually exclusive\n" + if $en && $dis; + +die "--module cannot be used with --enable-* or --disable-*\n" + if $module && ($en || $dis); + +die "$module: unknown module\n" if $module && ! grep $module,@{$lbmodules{lb}},@{$lbmodules{security}},{$lbmodules{jp}}; + +if ($dis) { + for (@nodes) { + $enable_nodes{$_} = 1 unless $disable_nodes{$_}; + } +} + +if (!$en && !$dis) { $enable_nodes{$_} = 1 for (@nodes) } ; + +for (keys %enable_nodes) { delete $enable_nodes{$_} unless $enable_nodes{$_}; } + +$stagedir = $prefix unless $stagedir; + +if ($mode eq 'build') { + print "Writing config.status\n"; + open CONF,">config.status" or die "config.status: $!\n"; + print CONF "$0 @keeparg\n"; + close CONF; +} + + +my @modules; +my %aux; + +if ($module) { +# push @modules,split(/[,.]+/,$module); + push @modules,$module; +} +else { + @modules = map(($extranodmod{$_} ? $extranodmod{$_} : 'lb.'.$_),(keys %enable_nodes)); + + my $n; + + do { + local $"="\n"; + $n = $#modules; + push @modules,(map @{$deps{$_}},@modules); + + undef %aux; @aux{@modules} = (1) x ($#modules+1); + @modules = keys %aux; + } while ($#modules > $n); +} + +@aux{@modules} = (1) x ($#modules+1); +delete $aux{$_} for (split /,/,$staged); +@modules = keys %aux; + +mode_build() if $mode eq 'build'; +mode_checkout() if $mode eq 'checkout'; +mode_etics($module) if $mode eq 'etics'; + +sub mode_build { + print "\nBuilding modules: @modules\n"; + + my @ext = map @{$need_externs{$_}},@modules; + my @myjars = map @{$need_jars{$_}},@modules; + undef %aux; @aux{@ext} = 1; + @ext = keys %aux; + undef %aux; @aux{@myjars} = (1) x ($#myjars+1); + @myjars = keys %aux; + + print "\nRequired externals:\n"; + print "\t$_: $extern_prefix{$_}\n" for @ext; + print "\t$_: $jar{$_}\n" for @myjars; + print "\nThis is a poor-man configure, it's up to you to have sources and externals there\n\n"; + + mkinc($_) for @modules; + + print "Creating Makefile\n"; + + open MAK,">Makefile" or die "Makefile: $!\n"; + + print MAK "all: @modules\n\nclean:\n"; + + for (@modules) { + my $full = full($_); + print MAK "\tcd $full/$buildroot{$_} && \${MAKE} clean\n" + } + + print MAK "\ndistclean:\n"; + + for (@modules) { + my $full = full($_); + print MAK $buildroot{$_} eq '' ? + "\tcd $full && \${MAKE} distclean\n" : + "\trm -rf $full/$buildroot{$_}\n" + } + + print MAK "\n"; + + for (@modules) { + my %ldeps; undef %ldeps; + @ldeps{@{$deps{$_}}} = 1; + for my $x (split /,/,$staged) { delete $ldeps{$x}; } + my @dnames = $module ? () : keys %ldeps; + + my $full = full($_); + my $build = $buildroot{$_}; + + print MAK "$_: @dnames\n\tcd $full/$build && \${MAKE} && \${MAKE} install\n\n"; + } + + close MAK; +} + +sub mode_checkout() { + for (@modules) { + my $module = $_; + my $tag = ""; + if ($lb_tag){ + for (@{$lbmodules{lb}}){ + if ("lb.".$_ eq $module){ + $tag = '-r '.$lb_tag; + } + } + } + if ($lbjp_tag){ + for (@{$lbmodules{'lbjp-common'}}){ + if ("lbjp-common.".$_ eq $module){ + $tag = '-r '.$lbjp_tag; + } + } + } + if ($jp_tag){ + for (@{$lbmodules{'jp'}}){ + if ("jp.".$_ eq $module){ + $tag = '-r '.$jp_tag; + } + } + } + if ($sec_tag){ + for (@{$lbmodules{security}}){ + if ("security.".$_ eq $module){ + $tag = '-r '.$sec_tag; + } + } + } + if ($jobid_tag){ + for (@{$lbmodules{jobid}}){ + if ("jobid.".$_ eq $module){ + $tag = '-r '.$jobid_tag; + } + } + } + #if (grep {"lb.".$_ eq $module} @{$lbmodules{lb}}){ + # print "found"; + #} + $_ = full($_); + print "\n*** Checking out $_\n"; + system("cvs checkout $tag $_") == 0 or die "cvs checkout $tag $_: $?\n"; + } +} + +BEGIN{ +%need_externs_aux = ( + 'lb.client' => [ qw/cppunit:B classads/ ], + 'lb.client-java' => [ qw/ant:B jdk:B axis:B trustmanager utiljava/ ], + 'lb.common' => [ qw/expat cares:B cppunit:B classads/ ], + 'lb.doc' => [], + 'lb.logger' => [ qw/cppunit:B/ ], + 'lb.server' => [ qw/globus_essentials:R globus:B expat cares mysql:R mysql-server:R mysql-devel:B cppunit:B gsoap:B classads voms lcas gridsite/ ], + 'lb.state-machine' => [ qw/classads/ ], + 'lb.utils' => [ qw/cppunit:B/ ], + 'lb.ws-interface' => [], + 'lb.ws-test' => [ qw/gsoap:B/ ], + 'lb.types' => [ qw// ], + 'lb.harvester' => [ qw// ], + 'lb.yaim' => [ qw/yaim_core:R/ ], + 'lb.glite-LB' => [ qw/fetchcrl:R gpt:R gip_release:R gip_service:R bdii:R glite_version:R glite_info_templates:R glue_schema:R/ ], + 'lbjp-common.db' => [ qw/mysql:B mysql-devel:B postgresql:B cppunit:B log4c:B/ ], + 'lbjp-common.log' => [ qw/log4c/ ], + 'lbjp-common.maildir' => [ qw// ], + 'lbjp-common.server-bones' => [ qw// ], + 'lbjp-common.trio' => [ qw/cppunit:B/ ], + 'lbjp-common.jp-interface' => [ qw/cppunit:B log4c:B/ ], + 'security.gss' => [ qw/globus_essentials:R globus:B cares cppunit:B/ ], + 'security.gsoap-plugin' => [ qw/cppunit:B globus_essentials:R globus:B cares:B gsoap:B/ ], + 'jobid.api-c' => [ qw/cppunit:B/ ], + 'jobid.api-cpp' => [ qw/cppunit:B/ ], + 'jobid.api-java' => [ qw/ant:B jdk:B/ ], + 'jp.client' => [ qw/gsoap libtar globus_essentials:R globus:B/ ], + 'jp.doc' => [], + 'jp.index' => [ qw/gsoap globus_essentials:R globus:B/ ], + 'jp.primary' => [ qw/classads gsoap libtar globus_essentials:R globus:B/ ], + 'jp.server-common' => [], + 'jp.ws-interface' => [], + 'gridsite.core' => [qw/httpd-devel:B gsoap:B globus:B/ ], +); + +for my $ext (keys %need_externs_aux) { + for (@{$need_externs_aux{$ext}}) { + /([^:]*)(?::(.*))?/; + push @{$need_externs{$ext}},$1; + my $type = $2 ? $2 : 'BR'; + $need_externs_type{$ext}->{$1} = $type; + } +} + +%need_jars = ( + 'jobid.api-java' => [ qw/commons-codec/ ], + 'lb.client-java' => [ qw/commons-lang/ ], +); + +for my $jar (keys %need_jars) { + for (@{$need_jars{$jar}}) { + $need_externs_type{$jar}->{$_} = 'BR'; # XXX + } +} + +%deps_aux = ( + 'lb.client' => [ qw/ + lb.types:B lb.common + lbjp-common.trio + jobid.api-cpp:B jobid.api-c + security.gss + / ], + 'lb.client-java' => [ qw/ + lb.types:B + lb.ws-interface:B + jobid.api-java + / ], + 'lb.common' => [ qw/ + jobid.api-cpp:B jobid.api-c + lb.types:B lbjp-common.trio security.gss + / ], + 'lb.doc' => [ qw/lb.types:B/ ], + 'lb.logger' => [ qw/ + lbjp-common.trio + lbjp-common.log + jobid.api-c + lb.common + security.gss + / ], + 'lb.server' => [ qw/ + lb.ws-interface lb.types:B lb.common lb.state-machine + lbjp-common.db lbjp-common.server-bones lbjp-common.trio lbjp-common.maildir lbjp-common.log + jobid.api-c + security.gsoap-plugin security.gss + / ], + 'lb.state-machine' => [ qw/lb.types:B lb.common lbjp-common.jp-interface security.gss/ ], + 'lb.utils' => [ qw/ + lbjp-common.jp-interface + jobid.api-c + lbjp-common.trio lbjp-common.maildir + lb.client lb.state-machine + / ], + 'lb.ws-test' => [ qw/security.gsoap-plugin lb.ws-interface/ ], + 'lb.ws-interface' => [ qw/lb.types:B/ ], + 'lb.types' => [ qw// ], + 'lb.harvester' => [ qw/ + jobid.api-c lbjp-common.trio lbjp-common.db lb.common lb.client + security.gss lbjp-common.log + / ], + 'lb.yaim' => [ qw// ], + 'lb.glite-LB' => [ qw/ + lb.logger:R lb.server:R lb.utils:R lb.doc:R + lb.ws-test:R lb.harvester:R lb.yaim:R lb.client-java:R + / ], + 'lbjp-common.db' => [ qw/lbjp-common.trio lbjp-common.log/ ], + 'lbjp-common.maildir' => [ qw// ], + 'lbjp-common.log' => [ qw// ], + 'lbjp-common.server-bones' => [ qw/lbjp-common.log/ ], + 'lbjp-common.trio' => [ qw// ], + 'security.gss' => [ qw// ], + 'security.gsoap-plugin' => [ qw/security.gss/ ], + 'jobid.api-c' => [ qw// ], + 'jobid.api-cpp' => [ qw/jobid.api-c/ ], + 'jobid.api-java' => [ qw// ], + + 'lbjp-common.jp-interface' => [ qw/lbjp-common.db jobid.api-c/ ], + + 'jp.client' => [ qw/ + jp.ws-interface + lbjp-common.jp-interface lbjp-common.maildir + jobid.api-c + security.gsoap-plugin + / ], + 'jp.doc' => [ qw// ], + 'jp.index' => [ qw/ + jp.server-common jp.ws-interface + lbjp-common.jp-interface lbjp-common.trio lbjp-common.db lbjp-common.server-bones + security.gsoap-plugin + / ], + 'jp.primary' => [ qw/ + jobid.api-c + jp.server-common jp.ws-interface + lb.state-machine + lbjp-common.jp-interface lbjp-common.trio lbjp-common.db lbjp-common.server-bones + security.gsoap-plugin + / ], + 'jp.server-common' => [ qw/ + lbjp-common.jp-interface lbjp-common.db + / ], + 'jp.ws-interface' => [ qw// ], + + 'gridsite.core' => [ qw/build.common-cpp:B/ ], +); + +for my $ext (keys %deps_aux) { + for (@{$deps_aux{$ext}}) { + /([^:]*)(?::(.*))?/; + push @{$deps{$ext}},$1; + my $type = $2 ? $2 : 'BR'; + $deps_type{$ext}->{$1} = $type; + } +} + + +%extrafull = ( gridsite=>'org.gridsite.core'); + +#( java => 'client-java' ); +%extranodmod = ( + db => 'lbjp-common.db', + jpprimary => 'jp.primary', + jpindex => 'jp.index', + jpclient => 'jp.client', +); + +%obsoletes = ( + 'lb.yaim' => [ qq/glite-yaim-lb/ ], +); + +%cvs_prefix = ( + 'lb' => 'org.glite', + 'jp' => 'org.glite', + 'jobid' => 'org.glite', + 'lbjp-common' => 'org.glite', + 'gridsite' => 'org', + 'security' => 'org.glite', +); + +%conf_prefix = ( + 'lb' => 'glite-', + 'jp' => 'glite-', + 'jobid' => 'glite-', + 'lbjp-common' => 'glite-', + 'gridsite' => '', + 'security' => 'glite-', +); + +my @k = keys %deps_aux; +@buildroot{@k} = ('build') x ($#k+1); + +my @t = qw/lb.client-java jobid.api-java lb.types/; +@buildroot{@t} = ('') x ($#t+1); + +$buildroot{'gridsite.core'} = 'src'; +} + +sub full +{ + my $short = shift; + return $extrafull{$short} ? $extrafull{$short} : 'org.glite.'.$short; +} + +sub mkinc +{ + my %aux; + undef %aux; + my @m=qw/ +lb.client lb.doc lb.state-machine lb.ws-interface lb.logger lb.types lb.common lb.server lb.utils lb.ws-test lb.client-java lb.harvester lb.yaim lb.glite-LB +security.gss security.gsoap-plugin +jobid.api-c jobid.api-cpp jobid.api-java +lbjp-common.db lbjp-common.log lbjp-common.maildir lbjp-common.server-bones lbjp-common.trio lbjp-common.jp-interface +jp.client jp.doc jp.index jp.primary jp.server-common jp.ws-interface +/; + @aux{@m} = (1) x ($#m+1); + + my $short = shift; + my $full = full $short; + + unless ($aux{$short}) { + print "Makefile.inc not needed in $full\n"; + return; + } + + my $build = ''; + + unless ($buildroot{$_} eq '') { + $build = "/$buildroot{$_}"; + unless (-d "$full/$buildroot{$_}") { + mkdir "$full/$buildroot{$_}" or die "mkdir $full/$buildroot{$_}: $!\n"; + } + unlink "$full/$buildroot{$_}/Makefile"; + symlink "../Makefile","$full/$buildroot{$_}/Makefile" or die "symlink ../Makefile $full/$buildroot{$_}/Makefile: $!\n"; + } + + open MKINC,">$full/$buildroot{$_}/Makefile.inc" + or die "$full/$buildroot{$_}/Makefile.inc: $!\n"; + + print "Creating $full/$buildroot{$_}/Makefile.inc\n"; + + print MKINC qq{ +PREFIX = $prefix +stagedir = $stagedir +thrflavour = $thrflavour +nothrflavour = $nothrflavour +libdir = $libdir +}; + + for (@{$need_externs{$short}}) { + print MKINC "${_}_prefix = $extern_prefix{$_}\n" + } + + for (@{$need_jars{$short}}) { + print MKINC "${_}_jar = $jar{$_}\n" + } + + my $need_gsoap = 0; + for (@{$need_externs{$short}}) { $need_gsoap = 1 if $_ eq 'gsoap'; } + + print MKINC "gsoap_default_version=".gsoap_version()."\n" if $need_gsoap; + + close MKINC; +} + +my %etics_externs; +my %etics_projects; +BEGIN{ + %etics_externs = ( + globus_essentials=>'vdt_globus_essentials', + globus=>'globus', + cares=>'c-ares', + voms=>'org.glite.security.voms-api-cpp', + gridsite=>'org.gridsite.shared', + lcas=>'org.glite.security.lcas', + trustmanager=>'org.glite.security.trustmanager', + utiljava=>'org.glite.security.util-java', + gpt=>'gpt', + fetchcrl=>'fetch-crl', + gip_release=>'glite-info-provider-release', + gip_service=>'glite-info-provider-service', + bdii=>'bdii', + glite_version=>'glite-version', + glite_info_templates=>'glite-info-templates', + glue_schema=>'glue-schema', + yaim_core=>'org.glite.yaim.core', + ); + %etics_projects = ( + vdt=>[qw/globus globus_essentials/], + 'org.glite'=>[qw/voms gridsite lcas gpt gip_release gip_service bdii glite_version glite_info_templates glue_schema yaim_core/], + ); + + %platform_properties = ( + 'gridsite.core' => { + sl5_x86_64_gcc412 => { aprSuffix => '1' }, + sl5_ia32_gcc412 => { aprSuffix => '1' }, + deb5_x86_64_gcc432 => { aprSuffix => '1.0' }, + deb5_ia32_gcc432 => { aprSuffix => '1.0' }, + slc4_x86_64_gcc346 => { aprSuffix => '0' }, + slc4_ia32_gcc346 => { aprSuffix => '0' }, + default => { + } + }, + ); +}; + +sub mode_etics { + $fmod = shift; + + die "$0: --module required with --etics\n" unless $fmod; + + my ($subsys,$module) = split /\./,$fmod; + + my ($major,$minor,$rev,$age); + + if ($version) { + $version =~ /([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)-(.+)/; + ($major,$minor,$rev,$age) = ($1,$2,$3,$4); + } + else { + open V,"$cvs_prefix{$subsys}.$subsys.$module/project/version.properties" + or die "$cvs_prefix{$subsys}.$subsys.$module/project/version.properties: $!\n"; + + while ($_ = ) { + chomp; + ($major,$minor,$rev) = ($1,$2,$3) if /module\.version\s*=\s*([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)/; + $age = $1 if /module\.age\s*=\s*([[:digit:]]+)/; + } + close V; + } + + my @copts = (); + my %ge; + @ge{@{$etics_projects{'org.glite'}}} = (1) x ($#{$etics_projects{'org.glite'}}+1); + + for (@{$need_externs{"$subsys.$module"}}) { + if ($need_externs_type{"$subsys.$module"}->{$_}=~/B/) { + my $eext = $etics_externs{$_} ? $etics_externs{$_} : $_; + push @copts,$ge{$_} ? "--with-$_=\${stageDir}" : "--with-$_=\${$eext.location}"; + } + } + + for (@{$need_jars{"$subsys.$module"}}) { + my $eext = $etics_externs{$_} ? $etics_externs{$_} : $_; + + push @copts,"--with-$_ \${$eext.location}/$_*.jar"; + } + + my $conf; + my $conftag; + + $dwpath = "path = \${projectName}/\${moduleName}/\${version}/\${platformName}/\${packageName}-\${version}-\${age}.tar.gz\n"; + if ($branch) { + $conf = "$conf_prefix{$subsys}${subsys}-${module}_$branch"; + $conftag = $branch; + $age = '0dev'; } + else { + $conf = "$conf_prefix{$subsys}$subsys-${module}_R_${major}_${minor}_${rev}_${age}"; + +# XXX: gridsite hack + $conftag = $subsys eq 'gridsite' ? "$conf_prefix{$subsys}$subsys-${module}_R_${major}_${minor}_${rev}" : $conf; } + my $file = $output ? $output : "$conf.ini"; + open C,">$file" or die "$file: $!\n"; + + my $buildroot = $buildroot{"$subsys.$module"} eq '' ? '#no build.root' : "build.root = " . $buildroot{"$subsys.$module"}; + + my $confdir = $buildroot{"$subsys.$module"} eq '' ? '..' : '../..'; + + my $package_description = ""; + my $package_summary = ""; + + if (-e "$cvs_prefix{$subsys}.$subsys.$module/project/package.description") { + open V, "$cvs_prefix{$subsys}.$subsys.$module/project/package.description"; + $package_description = join ("", ); + close V; + chomp $package_description; + $package_description =~ s/\n/\\n/g; + $package_description = "package.description = $package_description\n"; + } + else { + print STDERR "package.description not found for $subsys.$module!\n"; } + + if (-e "$cvs_prefix{$subsys}.$subsys.$module/project/package.summary") { + open V, "$cvs_prefix{$subsys}.$subsys.$module/project/package.summary"; + $package_summary = join ("", ); + close V; + chomp $package_summary; + $package_summary =~ s/\n/\\n/g; + $package_summary = "package.summary = $package_summary\n"; + } + else { + print STDERR "package.summary not found for $subsys.$module!\n"; } + + my %cmd; + @cmd{qw/configure compile test install packaging clean/} = ('None') x 6; + $cmd{clean} = 'make clean'; + + if ($subsys eq 'gridsite') { + if ($module eq 'core') { + my $flags = 'RELEASE_VERSION=${age}.${platformFamily} prefix=${prefix} libdir=${libdir} GSOAPDIR=${gsoap.location} OPENSSL_GLOBUS_FLAGS=-I${globus.location}/include/${globus.dbg.nothr.flavor} OPENSSL_GLOBUS_LIBS=-L${globus.location}/${libdir}/ FLAVOR_GLOBUS_EXT=_${globus.dbg.nothr.flavor} HTTPD_FLAGS="-I${httpd-devel.location}/include/httpd -I${httpd-devel.location}/include/apache2 -I${httpd-devel.location}/include/apr-${aprSuffix} -I${httpd-devel.location}/include/pcre"'; + + $cmd{compile} = "make $flags build"; + $cmd{install} = "make $flags install"; + $cmd{packaging} = "make $flags rpm"; + } + else { + $cmd{packaging} = "echo building nothing, org.gridsite.core make rpm step will create this"; + } + } + else { + $cmd{configure} = "cd $confdir && /usr/bin/perl \${moduleName}/configure --thrflavour=\${globus.thr.flavor} --nothrflavour=\${globus.nothr.flavor} --prefix=\${prefix} --stage=\${stageDir} --libdir=\${libdir} --module $subsys.$module @copts"; + $cmd{compile} = 'make'; + $cmd{test} = 'make check'; + $cmd{install} = 'make install'; + } + + my $defprops = ''; + + for my $p (keys %{$platform_properties{"$subsys.$module"}->{default}}) { + $defprops .= $p . ' = ' . $platform_properties{"$subsys.$module"}->{default}->{$p} . "\n"; + } + + print STDERR "Writing $file\n"; + print C qq{ +[Configuration-$conf] +profile = None +moduleName = $cvs_prefix{$subsys}.$subsys.$module +displayName = $conf +description = $cvs_prefix{$subsys}.$subsys.$module +projectName = org.glite +age = $age +deploymentType = None +tag = $conftag +version = $major.$minor.$rev +$dwpath +[Platform-default:VcsCommand] +displayName = None +description = None +tag = cvs -d \${vcsroot} tag -R \${tag} \${moduleName} +branch = None +commit = None +checkout = cvs -d \${vcsroot} co -r \${tag} \${moduleName} + +[Platform-default:BuildCommand] +postpublish = None +packaging = $cmd{packaging} +displayName = None +description = None +doc = None +prepublish = None +publish = None +compile = $cmd{compile} +init = None +install = $cmd{install} +clean = $cmd{clean} +test = $cmd{test} +configure = $cmd{configure} +checkstyle = None + +[Platform-default:Property] +$buildroot +aprSuffix = 0 +package.RPMSLocation = \${moduleDir}/RPMTMP/RPMS +package.SRPMSLocation = \${moduleDir}/RPMTMP/SRPMS +$package_description$package_summary$defprops +}; + for (@{$obsoletes{"$subsys.$module"}}) { + print C "package.obsoletes = $_\n"; + print C "package.replaces = $_\n"; + } + + for my $pp (keys %{$platform_properties{"$subsys.$module"}}) { + next if $pp eq 'default'; + print C "[Platform-$pp:Property]\n$buildroot\n"; + + for my $p (keys %{$platform_properties{"$subsys.$module"}->{$pp}}) { + print C $p . ' = ' . $platform_properties{"$subsys.$module"}->{$pp}->{$p} . "\n"; + } + print C q{package.RPMSLocation = ${moduleDir}/RPMTMP/RPMS +package.SRPMSLocation = ${moduleDir}/RPMTMP/SRPMS +}; + print C "$package_description$package_summary\n"; + } + + print C qq{ +[Platform-default:DynamicDependency] +}; + for (@{$need_externs{"$subsys.$module"}},@{$need_jars{"$subsys.$module"}}) { + my $eext = $etics_externs{$_} ? $etics_externs{$_} : $_; + + my $proj = 'externals'; + for my $p (keys %etics_projects) { + for $m (@{$etics_projects{$p}}) { + $proj = $p if $m eq $_; + } + } + + my $type = $need_externs_type{"$subsys.$module"}->{$_}; + print C "$proj|$eext = $type\n"; + } + + for (@{$deps{"$subsys.$module"}}) { + my $type = $deps_type{"$subsys.$module"}->{$_}; + print C "org.glite|org.glite.$_ = $type\n"; + } + + close C; +} + +sub gsoap_version { + local $_; + my $gsoap_version; + open S,"$extern_prefix{gsoap}/bin/soapcpp2 -v 2>&1 |" or die "$extern_prefix{gsoap}/bin/soapcpp2: $!\n"; + + while ($_ = ) { + chomp; + + $gsoap_version = $1 if /The gSOAP Stub and Skeleton Compiler for C and C\+\+ ([.[:digit:][:alpha:]]+)$/; + } + close S; + return $gsoap_version; +} + +sub getlibdir { + if ( -e "/etc/debian_version") { # We are on Debian + $lib64="lib"; + $lib32="lib32"; } + else { # Another distribution + $lib64="lib64"; + $lib32="lib"; } + $libdir=$lib32; + + open INP, "uname -s | "; # Check kernel name + $kname= ; + chomp($kname); + close INP; + + if ( $kname == "Linux") { + $arch = ("x86_64\npowerpc\nppc64\n"); + + open INP, "uname -p | "; # Check processor type + $procname= ; + chomp($procname); + close INP; + + if ($arch =~/^$procname\n/) { + return ($lib64); } + + open INP, "uname -m | "; # Check machine hardware + $machname= ; + chomp($machname); + close INP; + + if ($arch =~/^$machname\n/) { + return ($lib64); } + + # special cases (hyperlink lib64, Debian) + if (-l "/usr/lib64") { + $libdir=$lib32; } + + # if /usr/lib64 doesn't exist at all (AIX) + unless ( -e "/usr/lib64" ) { + $libdir=$lib32; } + } + + if ( $kname == "SunOS") { + if (-e "/usr/lib/64") { + $libdir="lib/64"; } + } + + return $libdir; +} + +sub usage { + my @ext = keys %extern_prefix; + my @myjars, keys %jar; + + print STDERR qq{ +usage: $0 options + +General options (defaults in []): + --prefix=PREFIX destination directory [./stage] + --staged=module,module,... what is already in PREFIX (specify without org.glite.) + --thrflavour=flavour + --nothrflavour=flavour threaded and non-treaded flavours [gcc64dbgpthr,gcc64dbg] + --listmodules=subsys list modules of a subsystem + --libdir=libdir typically [lib,lib64] postfix + +Mode of operation: + --mode={checkout|build|etics} what to do [build] + +What to build: + --module=module build this module only (mostly in-Etics operation) + --enable-NODE build this "node" (set of modules) only. Available nodes are + @{$lbmodules{lb}},@{$lbmodules{security}} + --disable-NODE don't build this node + --lb-tag=tag checkout LB modules with specific tag + --jp-tag=tag checkout JP modules with specific tag + --lbjp-common-tag=tag checkout lbjp-common modules with specific tag + --security-tag=tag checkout security modules with specific tag + --jobid-tag=tag checkout jobid modules with specific tag + +Dependencies: + --with-EXTERNAL=PATH where to look for an external. Required externals + (not all for all modules) are: + @ext + --with-JAR=JAR where to look for jars. Required jars are: + @myjars + Summary of what will be used is always printed + +}; + +} diff --git a/org.glite.lbjp-common.gss/interface/glite_gss.h b/org.glite.lbjp-common.gss/interface/glite_gss.h new file mode 100644 index 0000000..9468689 --- /dev/null +++ b/org.glite.lbjp-common.gss/interface/glite_gss.h @@ -0,0 +1,185 @@ +#ifndef __EDG_WORKLOAD_LOGGING_COMMON_LB_GSS_H__ +#define __EDG_WORKLOAD_LOGGING_COMMON_LB_GSS_H__ + +#ident "$Header$" +/* +Copyright (c) Members of the EGEE Collaboration. 2004-2010. +See http://www.eu-egee.org/partners for details on the copyright holders. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +enum { + EDG_WLL_GSS_OK = 0, /* no GSS errors */ + EDG_WLL_GSS_ERROR_GSS = -1, /* GSS specific error, call edg_wll_get_gss_error() for details */ + EDG_WLL_GSS_ERROR_TIMEOUT = -2, /* Timeout */ + EDG_WLL_GSS_ERROR_EOF = -3, /* EOF occured */ + EDG_WLL_GSS_ERROR_ERRNO = -4, /* System error. See errno */ + EDG_WLL_GSS_ERROR_HERRNO = -5 /* Resolver error. See h_errno */ +}; + +enum { + EDG_WLL_GSS_FLAG_DELEG = 1, + EDG_WLL_GSS_FLAG_CONF = 16, + EDG_WLL_GSS_FLAG_INTEG = 32, + EDG_WLL_GSS_FLAG_ANON = 64, +}; + +typedef void * edg_wll_GssCtx; + +typedef struct _edg_wll_GssConnection { + edg_wll_GssCtx context; + int sock; + char *buffer; + size_t bufsize; +} edg_wll_GssConnection; + +typedef struct _edg_wll_GssStatus { + unsigned int major_status; + unsigned int minor_status; +} edg_wll_GssStatus; + +typedef struct _edg_wll_GssPrincipal_data { + char *name; + unsigned int flags; + char **fqans; +#if 0 + char **voms_groups; /* needed for legacy LB server authZ mechanism */ + edg_wll_GssOid authn_mech; +#endif +} edg_wll_GssPrincipal_data; +typedef struct _edg_wll_GssPrincipal_data *edg_wll_GssPrincipal; + +typedef struct _edg_wll_GssCred_data { + void *gss_cred; + time_t lifetime; + char *name; +} _edg_wll_GssCred_data; +typedef struct _edg_wll_GssCred_data *edg_wll_GssCred; + +int +edg_wll_gss_initialize(void); + +int +edg_wll_gss_acquire_cred_gsi(const char *cert_file, + const char *key_file, + edg_wll_GssCred *cred, + edg_wll_GssStatus* gss_code); + +int +edg_wll_gss_release_cred(edg_wll_GssCred *cred, + edg_wll_GssStatus* gss_code); + +int +edg_wll_gss_connect(edg_wll_GssCred cred, + char const *hostname, + int port, + struct timeval *timeout, + edg_wll_GssConnection *connection, + edg_wll_GssStatus* gss_code); + +int +edg_wll_gss_accept(edg_wll_GssCred cred, + int sock, + struct timeval *timeout, + edg_wll_GssConnection *connection, + edg_wll_GssStatus* gss_code); + +int +edg_wll_gss_read(edg_wll_GssConnection *connection, + void *buf, + size_t bufsize, + struct timeval *timeout, + edg_wll_GssStatus* gss_code); + +int +edg_wll_gss_write(edg_wll_GssConnection *connection, + const void *buf, + size_t bufsize, + struct timeval *timeout, + edg_wll_GssStatus* gss_code); + +int +edg_wll_gss_read_full(edg_wll_GssConnection *connection, + void *buf, + size_t bufsize, + struct timeval *timeout, + size_t *total, + edg_wll_GssStatus* gss_code); + +int +edg_wll_gss_write_full(edg_wll_GssConnection *connection, + const void *buf, + size_t bufsize, + struct timeval *timeout, + size_t *total, + edg_wll_GssStatus* gss_code); + +int +edg_wll_gss_watch_creds(const char * proxy_file, + time_t * proxy_mtime); + +int +edg_wll_gss_get_error(edg_wll_GssStatus* gss_code, + const char *prefix, + char **errmsg); + +int +edg_wll_gss_close(edg_wll_GssConnection *connection, + struct timeval *timeout); + +int +edg_wll_gss_reject(int sock); + +int +edg_wll_gss_get_client_conn(edg_wll_GssConnection *connection, + edg_wll_GssPrincipal *principal, + edg_wll_GssStatus* gss_code); + +int +edg_wll_gss_get_client_pem(edg_wll_GssConnection *connection, + const char *my_cert_file, const char *my_key_file, + char **pem_string); + +void +edg_wll_gss_free_princ(edg_wll_GssPrincipal principal); + +int +edg_wll_gss_gethostname(char *name, int len); + +char * +edg_wll_gss_normalize_subj(char *in, + int replace_in); + +int +edg_wll_gss_equal_subj(const char *a, + const char *b); + +int +edg_wll_gss_unread(edg_wll_GssConnection *connection, + void *data, + size_t len); + +#ifdef __cplusplus +} +#endif + +#endif /* __EDG_WORKLOAD_LOGGING_COMMON_LB_GSS_H__ */ diff --git a/org.glite.lbjp-common.gss/project/ChangeLog b/org.glite.lbjp-common.gss/project/ChangeLog new file mode 100644 index 0000000..774ccb8 --- /dev/null +++ b/org.glite.lbjp-common.gss/project/ChangeLog @@ -0,0 +1,39 @@ +2.0.0-1 +- LB 2.0 release + +2.0.0-2 +- proper reference to cppunit + +2.0.0-3 +- globus flavors added to configure + +2.0.0-4 +- Module repacked. + +2.0.0-5 +- New age to fix an erroneous lock + +2.0.0-6 +- install libraries into $libdir + +2.0.1-1 +- Memleak fixes +- Working with c-ares >= 1.5.0 +- Added edg_wll_gss_unread() +- Consider arch libdir when linking c-ares + +2.1.0-1 +- IPv6 fixes + +2.1.1-1 +- Fixed making target 'check' + +2.1.2-1 +- Fixed target 'clean' in the Makefile to handle debian builds + +2.1.3-1 +- c-ares function call adjusted to new/old c-ares version + +2.1.4-1 +- Support IPv6 literal adresses. + diff --git a/org.glite.lbjp-common.gss/project/package.description b/org.glite.lbjp-common.gss/project/package.description new file mode 100644 index 0000000..3fc8dce --- /dev/null +++ b/org.glite.lbjp-common.gss/project/package.description @@ -0,0 +1 @@ +glite-security-gss wraps GSS functions (and several non-GSS Globus calls) to a secure network communication library with strict timing control (via timeout arguments) of all remote operations. diff --git a/org.glite.lbjp-common.gss/project/package.summary b/org.glite.lbjp-common.gss/project/package.summary new file mode 100644 index 0000000..4b2ef0e --- /dev/null +++ b/org.glite.lbjp-common.gss/project/package.summary @@ -0,0 +1 @@ +Wrapper of Globus GSS/SSL implementation used by gLite LB and JP diff --git a/org.glite.lbjp-common.gss/project/version.properties b/org.glite.lbjp-common.gss/project/version.properties new file mode 100644 index 0000000..6e8c734 --- /dev/null +++ b/org.glite.lbjp-common.gss/project/version.properties @@ -0,0 +1,3 @@ +# $Header$ +module.version=2.1.4 +module.age=1 diff --git a/org.glite.lbjp-common.gss/src/glite_gss.c b/org.glite.lbjp-common.gss/src/glite_gss.c new file mode 100644 index 0000000..08a4349 --- /dev/null +++ b/org.glite.lbjp-common.gss/src/glite_gss.c @@ -0,0 +1,1536 @@ +#ident "$Header$" +/* +Copyright (c) Members of the EGEE Collaboration. 2004-2010. +See http://www.eu-egee.org/partners for details on the copyright holders. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "glite_gss.h" + +#define tv_sub(a,b) {\ + (a).tv_usec -= (b).tv_usec;\ + (a).tv_sec -= (b).tv_sec;\ + if ((a).tv_usec < 0) {\ + (a).tv_sec--;\ + (a).tv_usec += 1000000;\ + }\ +} + +struct asyn_result { + struct hostent *ent; + int err; +}; + +static int decrement_timeout(struct timeval *timeout, struct timeval before, struct timeval after) +{ + (*timeout).tv_sec = (*timeout).tv_sec - (after.tv_sec - before.tv_sec); + (*timeout).tv_usec = (*timeout).tv_usec - (after.tv_usec - before.tv_usec); + while ( (*timeout).tv_usec < 0) { + (*timeout).tv_sec--; + (*timeout).tv_usec += 1000000; + } + if ( ((*timeout).tv_sec < 0) || (((*timeout).tv_sec == 0) && ((*timeout).tv_usec == 0)) ) return(1); + else return(0); +} + +/* ares callback handler for ares_gethostbyname() */ +#if ARES_VERSION >= 0x010500 +static void callback_ares_gethostbyname(void *arg, int status, int timeouts, struct hostent *h) +#else +static void callback_ares_gethostbyname(void *arg, int status, struct hostent *h) +#endif +{ + struct asyn_result *arp = (struct asyn_result *) arg; + + switch (status) { + case ARES_SUCCESS: + if (h && h->h_addr_list[0]) { + arp->ent->h_addr_list = + (char **) malloc(2 * sizeof(char *)); + if (arp->ent->h_addr_list == NULL) { + arp->err = NETDB_INTERNAL; + break; + } + arp->ent->h_addr_list[0] = + malloc(h->h_length); + if (arp->ent->h_addr_list[0] == NULL) { + free(arp->ent->h_addr_list); + arp->err = NETDB_INTERNAL; + break; + } + memcpy(arp->ent->h_addr_list[0], h->h_addr_list[0], + h->h_length); + arp->ent->h_addr_list[1] = NULL; + arp->ent->h_addrtype = h->h_addrtype; + arp->err = NETDB_SUCCESS; + } else { + arp->err = NO_DATA; + } + break; + case ARES_EBADNAME: + case ARES_ENOTFOUND: + arp->err = HOST_NOT_FOUND; + break; + case ARES_ENOTIMP: + arp->err = NO_RECOVERY; + break; + case ARES_ENOMEM: + case ARES_EDESTRUCTION: + default: + arp->err = NETDB_INTERNAL; + break; + } +} + +static void free_hostent(struct hostent *h){ + int i; + + if (h) { + if (h->h_name) free(h->h_name); + if (h->h_aliases) { + for (i=0; h->h_aliases[i]; i++) free(h->h_aliases[i]); + free(h->h_aliases); + } + if (h->h_addr_list) { + for (i=0; h->h_addr_list[i]; i++) free(h->h_addr_list[i]); + free(h->h_addr_list); + } + free(h); + } +} + +static int asyn_getservbyname2(int af, struct sockaddr_storage *addrOut, socklen_t *a_len,char const *name, int port, struct timeval *timeout) { + struct asyn_result ar; + ares_channel channel; + int nfds; + fd_set readers, writers; + struct timeval tv, *tvp; + struct timeval start_time,check_time; + int err = NETDB_INTERNAL; + char *name2, *p; + size_t namelen; + + name2 = name; + namelen = strlen(name); + if (name[0]=='[' && name[namelen-1]==']') { + /* IPv6 literal, strip brackets */ + name2 = strdup(name); + if (!name2) return NETDB_INTERNAL; + name2[namelen-1] = '\0'; + name2++; + /* Ignore scope identifier, not supported by c-ares */ + p = strchr(name2, '%'); + if (p) *p = '\0'; + } + +/* start timer */ + gettimeofday(&start_time,0); + +/* ares init */ + if ( ares_init(&channel) != ARES_SUCCESS ) return(NETDB_INTERNAL); + ar.ent = (struct hostent *) calloc (sizeof(*ar.ent),1); + +/* query DNS server asynchronously */ + ares_gethostbyname(channel, name2, af, callback_ares_gethostbyname, + (void *) &ar); + +/* wait for result */ + while (1) { + FD_ZERO(&readers); + FD_ZERO(&writers); + nfds = ares_fds(channel, &readers, &writers); + if (nfds == 0) + break; + + gettimeofday(&check_time,0); + if (timeout && decrement_timeout(timeout, start_time, check_time)) { + ares_destroy(channel); + free_hostent(ar.ent); + return(TRY_AGAIN); + } + start_time = check_time; + + tvp = ares_timeout(channel, timeout, &tv); + + switch ( select(nfds, &readers, &writers, NULL, tvp) ) { + case -1: if (errno != EINTR) { + ares_destroy(channel); + free_hostent(ar.ent); + return NETDB_INTERNAL; + } else + continue; + case 0: + FD_ZERO(&readers); + FD_ZERO(&writers); + /* fallthrough */ + default: ares_process(channel, &readers, &writers); + } + } + + if (ar.err == NETDB_SUCCESS) { + struct sockaddr_in *p4 = (struct sockaddr_in *)addrOut; + struct sockaddr_in6 *p6 = (struct sockaddr_in6 *)addrOut; + + memset(addrOut, 0, sizeof *addrOut); + addrOut->ss_family = ar.ent->h_addrtype; + switch (ar.ent->h_addrtype) { + case AF_INET: + memcpy(&p4->sin_addr,ar.ent->h_addr_list[0], sizeof(struct in_addr)); + p4->sin_port = htons(port); + *a_len = sizeof (struct sockaddr_in); + break; + case AF_INET6: + memcpy(&p6->sin6_addr,ar.ent->h_addr_list[0], sizeof(struct in6_addr)); + p6->sin6_port = htons(port); + *a_len = sizeof (struct sockaddr_in6); + break; + default: + return NETDB_INTERNAL; + break; + } + } + free_hostent(ar.ent); ar.ent = NULL; + err = ar.err; + + /* literal conversion should always succeed */ + if (name2 != name) free(name2-1); + + ares_destroy(channel); + + return err; +} + +static int asyn_getservbyname(struct sockaddr_storage *addrOut, socklen_t *a_len,char const *name, int port, struct timeval *timeout) { + int res; + + res = asyn_getservbyname2(AF_INET6, addrOut, a_len, name, port, timeout); + if (res != HOST_NOT_FOUND) return res; + res = asyn_getservbyname2(AF_INET, addrOut, a_len, name, port, timeout); + return res; +} + +static int +do_connect(int *s, char const *hostname, int port, struct timeval *timeout) +{ + int sock; + struct timeval before,after,to; + struct sockaddr_storage a; + socklen_t a_len; + int sock_err; + socklen_t err_len; + int h_errno; + int opt; + + /* XXX todo: try multiple addresses */ + switch (h_errno = asyn_getservbyname(&a, &a_len, hostname, port, timeout)) { + case NETDB_SUCCESS: + break; + case TRY_AGAIN: + close(sock); + return EDG_WLL_GSS_ERROR_TIMEOUT; + case NETDB_INTERNAL: + /* fall through */ + default: + close(sock); + /* h_errno may be thread safe with Linux pthread libs, + * but such an assumption is not portable + */ + errno = h_errno; + return EDG_WLL_GSS_ERROR_HERRNO; + } + + sock = socket(a.ss_family, SOCK_STREAM, 0); + if (sock < 0) return EDG_WLL_GSS_ERROR_ERRNO; + + opt = 1; + setsockopt(sock,IPPROTO_TCP,TCP_NODELAY,&opt,sizeof opt); + + if (timeout) { + int flags = fcntl(sock, F_GETFL, 0); + if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) < 0) + return EDG_WLL_GSS_ERROR_ERRNO; + gettimeofday(&before,NULL); + } + + if (connect(sock,(struct sockaddr *) &a, a_len) < 0) { + if (timeout && errno == EINPROGRESS) { + fd_set fds; + FD_ZERO(&fds); + FD_SET(sock,&fds); + memcpy(&to,timeout,sizeof to); + gettimeofday(&before,NULL); + switch (select(sock+1,NULL,&fds,NULL,&to)) { + case -1: close(sock); + return EDG_WLL_GSS_ERROR_ERRNO; + case 0: close(sock); + return EDG_WLL_GSS_ERROR_TIMEOUT; + } + gettimeofday(&after,NULL); + tv_sub(after,before); + tv_sub(*timeout,after); + + err_len = sizeof sock_err; + if (getsockopt(sock,SOL_SOCKET,SO_ERROR,&sock_err,&err_len)) { + close(sock); + return EDG_WLL_GSS_ERROR_ERRNO; + } + if (sock_err) { + close(sock); + errno = sock_err; + return EDG_WLL_GSS_ERROR_ERRNO; + } + } + else { + close(sock); + return EDG_WLL_GSS_ERROR_ERRNO; + } + } + + *s = sock; + return 0; +} + +static int +send_token(int sock, void *token, size_t token_length, struct timeval *to) +{ + size_t num_written = 0; + ssize_t count; + fd_set fds; + struct timeval timeout,before,after; + int ret; + + if (to) { + memcpy(&timeout,to,sizeof(timeout)); + gettimeofday(&before,NULL); + } + + + ret = 0; + while(num_written < token_length) { + FD_ZERO(&fds); + FD_SET(sock,&fds); + switch (select(sock+1, NULL, &fds, NULL, to ? &timeout : NULL)) { + case 0: ret = EDG_WLL_GSS_ERROR_TIMEOUT; + goto end; + break; + case -1: ret = EDG_WLL_GSS_ERROR_ERRNO; + goto end; + break; + } + + count = write(sock, ((char *)token) + num_written, + token_length - num_written); + if(count < 0) { + if(errno == EINTR) + continue; + else { + ret = EDG_WLL_GSS_ERROR_ERRNO; + goto end; + } + } + num_written += count; + } + +end: + if (to) { + gettimeofday(&after,NULL); + tv_sub(after,before); + tv_sub(*to,after); + if (to->tv_sec < 0) { + to->tv_sec = 0; + to->tv_usec = 0; + } + } + + return ret; +} + +static int +recv_token(int sock, void **token, size_t *token_length, struct timeval *to) +{ + ssize_t count; + char buf[4098]; + char *t = NULL; + char *tmp; + size_t tl = 0; + fd_set fds; + struct timeval timeout,before,after; + int ret; + + if (to) { + memcpy(&timeout,to,sizeof(timeout)); + gettimeofday(&before,NULL); + } + + ret = 0; + do { + FD_ZERO(&fds); + FD_SET(sock,&fds); + switch (select(sock+1, &fds, NULL, NULL, to ? &timeout : NULL)) { + case 0: + ret = EDG_WLL_GSS_ERROR_TIMEOUT; + goto end; + break; + case -1: + ret = EDG_WLL_GSS_ERROR_ERRNO; + goto end; + break; + } + + count = read(sock, buf, sizeof(buf)); + if (count < 0) { + if (errno == EINTR) + continue; + else { + ret = EDG_WLL_GSS_ERROR_ERRNO; + goto end; + } + } + + if (count==0) { + if (tl==0) { + free(t); + return EDG_WLL_GSS_ERROR_EOF; + } else goto end; + } + tmp=realloc(t, tl + count); + if (tmp == NULL) { + errno = ENOMEM; + free(t); + return EDG_WLL_GSS_ERROR_ERRNO; + } + t = tmp; + memcpy(t + tl, buf, count); + tl += count; + + } while (count < 0); /* restart on EINTR */ + +end: + if (to) { + gettimeofday(&after,NULL); + tv_sub(after,before); + tv_sub(*to,after); + if (to->tv_sec < 0) { + to->tv_sec = 0; + to->tv_usec = 0; + } + } + + if (ret == 0) { + *token = t; + *token_length = tl; + } else + free(t); + + return ret; +} + +static int +create_proxy(const char *cert_file, const char *key_file, char **proxy_file) +{ + char buf[4096]; + int in, out; + char *name = NULL; + int ret, len; + + *proxy_file = NULL; + + asprintf(&name, "%s/%d.lb.XXXXXX", P_tmpdir, getpid()); + + out = mkstemp(name); + if (out < 0) + return EDG_WLL_GSS_ERROR_ERRNO; + + in = open(cert_file, O_RDONLY); + if (in < 0) { + ret = EDG_WLL_GSS_ERROR_ERRNO; + goto end; + } + while ((ret = read(in, buf, sizeof(buf))) > 0) { + len = write(out, buf, ret); + if (len != ret) { + ret = -1; + break; + } + } + close(in); + if (ret < 0) { + ret = EDG_WLL_GSS_ERROR_ERRNO; + goto end; + } + + len = write(out, "\n", 1); + if (len != 1) { + ret = EDG_WLL_GSS_ERROR_ERRNO; + goto end; + } + + in = open(key_file, O_RDONLY); + if (in < 0) { + ret = EDG_WLL_GSS_ERROR_ERRNO; + goto end; + } + while ((ret = read(in, buf, sizeof(buf))) > 0) { + len = write(out, buf, ret); + if (len != ret) { + ret = -1; + break; + } + } + close(in); + if (ret < 0) { + ret = EDG_WLL_GSS_ERROR_ERRNO; + goto end; + } + + ret = 0; + *proxy_file = name; + +end: + close(out); + if (ret) { + unlink(name); + free(name); + } + + return ret; +} + +static int +destroy_proxy(char *proxy_file) +{ + /* XXX we should erase the contents safely (i.e. overwrite with 0's) */ + unlink(proxy_file); + return 0; +} + +int +edg_wll_gss_acquire_cred_gsi(const char *cert_file, const char *key_file, edg_wll_GssCred *cred, + edg_wll_GssStatus* gss_code) +{ + OM_uint32 major_status = 0, minor_status, minor_status2; + gss_cred_id_t gss_cred = GSS_C_NO_CREDENTIAL; + gss_buffer_desc buffer = GSS_C_EMPTY_BUFFER; + gss_name_t gss_name = GSS_C_NO_NAME; + OM_uint32 lifetime; + char *proxy_file = NULL; + char *name = NULL; + int ret; + + if ((cert_file == NULL && key_file != NULL) || + (cert_file != NULL && key_file == NULL)) + return EINVAL; + + if (cert_file == NULL) { + major_status = gss_acquire_cred(&minor_status, GSS_C_NO_NAME, 0, + GSS_C_NO_OID_SET, GSS_C_BOTH, + &gss_cred, NULL, NULL); + if (GSS_ERROR(major_status)) { + ret = EDG_WLL_GSS_ERROR_GSS; + goto end; + } + } else { + proxy_file = (char *)cert_file; + if (strcmp(cert_file, key_file) != 0 && + (ret = create_proxy(cert_file, key_file, &proxy_file))) { + proxy_file = NULL; + goto end; + } + + asprintf((char**)&buffer.value, "X509_USER_PROXY=%s", proxy_file); + if (buffer.value == NULL) { + errno = ENOMEM; + ret = EDG_WLL_GSS_ERROR_ERRNO; + goto end; + } + buffer.length = strlen(proxy_file); + + major_status = gss_import_cred(&minor_status, &gss_cred, GSS_C_NO_OID, 1, + &buffer, 0, NULL); + free(buffer.value); + if (GSS_ERROR(major_status)) { + ret = EDG_WLL_GSS_ERROR_GSS; + goto end; + } + } + + /* gss_import_cred() doesn't check validity of credential loaded, so let's + * verify it now */ + major_status = gss_inquire_cred(&minor_status, gss_cred, &gss_name, + &lifetime, NULL, NULL); + if (GSS_ERROR(major_status)) { + ret = EDG_WLL_GSS_ERROR_GSS; + goto end; + } + + /* Must cast to time_t since OM_uint32 is unsinged and hence we couldn't + * detect negative values. */ + if ((time_t) lifetime <= 0) { + major_status = GSS_S_CREDENTIALS_EXPIRED; + minor_status = 0; /* XXX */ + ret = EDG_WLL_GSS_ERROR_GSS; + goto end; + } + + major_status = gss_display_name(&minor_status, gss_name, &buffer, NULL); + if (GSS_ERROR(major_status)) { + ret = EDG_WLL_GSS_ERROR_GSS; + goto end; + } + name = buffer.value; + memset(&buffer, 0, sizeof(buffer)); + + *cred = calloc(1, sizeof(**cred)); + if (*cred == NULL) { + ret = EDG_WLL_GSS_ERROR_ERRNO; + free(name); + goto end; + } + + (*cred)->gss_cred = gss_cred; + gss_cred = GSS_C_NO_CREDENTIAL; + (*cred)->lifetime = lifetime; + (*cred)->name = name; + + ret = 0; + +end: + if (cert_file && key_file && proxy_file && strcmp(cert_file, key_file) != 0) { + destroy_proxy(proxy_file); + free(proxy_file); + } + + if (gss_name != GSS_C_NO_NAME) + gss_release_name(&minor_status2, &gss_name); + + if (gss_cred != GSS_C_NO_CREDENTIAL) + gss_release_cred(&minor_status2, &gss_cred); + + if (GSS_ERROR(major_status)) { + if (gss_code) { + gss_code->major_status = major_status; + gss_code->minor_status = minor_status; + } + ret = EDG_WLL_GSS_ERROR_GSS; + } + + return ret; +} + +/* XXX XXX This is black magic. "Sometimes" server refuses the client with SSL + * * alert "certificate expired" even if it is not true. In this case the server + * * slave terminates (which helps, usually), and we can reconnect transparently. + * */ + +/* This string appears in the error message in this case */ +#define _EXPIRED_ALERT_MESSAGE "function SSL3_READ_BYTES: sslv3 alert certificate expired" +#define _EXPIRED_ALERT_RETRY_COUNT 10 /* default number of slaves, hope that not all + are in the bad state */ +#define _EXPIRED_ALERT_RETRY_DELAY 10 /* ms */ + +/* XXX XXX This is black magic. "Sometimes" server refuses the client with SSL + * * alert "certificate expired" even if it is not true. In this case the server + * * slave terminates (which helps, usually), and we can reconnect transparently. + * */ + +/* This string appears in the error message in this case */ +#define _EXPIRED_ALERT_MESSAGE "function SSL3_READ_BYTES: sslv3 alert certificate expired" +#define _EXPIRED_ALERT_RETRY_COUNT 10 /* default number of slaves, hope that not all + are in the bad state */ +#define _EXPIRED_ALERT_RETRY_DELAY 10 /* ms */ + +int +edg_wll_gss_connect(edg_wll_GssCred cred, char const *hostname, int port, + struct timeval *timeout, edg_wll_GssConnection *connection, + edg_wll_GssStatus* gss_code) +{ + int sock, ret; + OM_uint32 maj_stat, min_stat, min_stat2, req_flags; + int context_established = 0; + gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; + gss_name_t server = GSS_C_NO_NAME; + gss_ctx_id_t context = GSS_C_NO_CONTEXT; + char *servername = NULL; + int retry = _EXPIRED_ALERT_RETRY_COUNT; + + maj_stat = min_stat = min_stat2 = req_flags = 0; + memset(connection, 0, sizeof(*connection)); + + /* GSI specific */ + req_flags = GSS_C_GLOBUS_SSL_COMPATIBLE; + + ret = do_connect(&sock, hostname, port, timeout); + if (ret) + return ret; + + /* XXX find appropriate fqdn */ + asprintf (&servername, "host@%s", hostname); + if (servername == NULL) { + errno = ENOMEM; + ret = EDG_WLL_GSS_ERROR_ERRNO; + goto end; + } + input_token.value = servername; + input_token.length = strlen(servername) + 1; + + maj_stat = gss_import_name(&min_stat, &input_token, + GSS_C_NT_HOSTBASED_SERVICE, &server); + if (GSS_ERROR(maj_stat)) { + ret = EDG_WLL_GSS_ERROR_GSS; + goto end; + } + + free(servername); + memset(&input_token, 0, sizeof(input_token)); + + /* XXX if cred == GSS_C_NO_CREDENTIAL set the ANONYMOUS flag */ + + do { /* XXX: the black magic above */ + + /* XXX prepsat na do {} while (maj_stat == CONT) a osetrit chyby*/ + while (!context_established) { + /* XXX verify ret_flags match what was requested */ + maj_stat = gss_init_sec_context(&min_stat, cred->gss_cred, &context, + GSS_C_NO_NAME, GSS_C_NO_OID, + req_flags | GSS_C_MUTUAL_FLAG | GSS_C_CONF_FLAG, + 0, GSS_C_NO_CHANNEL_BINDINGS, + &input_token, NULL, &output_token, + NULL, NULL); + if (input_token.length > 0) { + free(input_token.value); + input_token.length = 0; + } + + if (output_token.length != 0) { + ret = send_token(sock, output_token.value, output_token.length, timeout); + gss_release_buffer(&min_stat2, &output_token); + if (ret) + goto end; + } + + if (GSS_ERROR(maj_stat)) { + if (context != GSS_C_NO_CONTEXT) { + gss_delete_sec_context(&min_stat2, &context, &output_token); + context = GSS_C_NO_CONTEXT; + if (output_token.length) { + send_token(sock, output_token.value, output_token.length, timeout); + gss_release_buffer(&min_stat2, &output_token); + } + } + ret = EDG_WLL_GSS_ERROR_GSS; + goto end; + } + + if(maj_stat & GSS_S_CONTINUE_NEEDED) { + ret = recv_token(sock, &input_token.value, &input_token.length, timeout); + if (ret) + goto end; + } else + context_established = 1; + } + + /* XXX check ret_flags matches to what was requested */ + + /* retry on false "certificate expired" */ + if (ret == EDG_WLL_GSS_ERROR_GSS) { + edg_wll_GssStatus gss_stat; + char *msg = NULL; + + gss_stat.major_status = maj_stat; + gss_stat.minor_status = min_stat; + edg_wll_gss_get_error(&gss_stat,"",&msg); + + if (strstr(msg,_EXPIRED_ALERT_MESSAGE)) { + usleep(_EXPIRED_ALERT_RETRY_DELAY); + retry--; + } + else retry = 0; + + free(msg); + } + else retry = 0; + + } while (retry); + + connection->sock = sock; + connection->context = context; + servername = NULL; + ret = 0; + +end: + if (ret == EDG_WLL_GSS_ERROR_GSS && gss_code) { + gss_code->major_status = maj_stat; + gss_code->minor_status = min_stat; + } + if (server != GSS_C_NO_NAME) + gss_release_name(&min_stat2, &server); + if (servername == NULL) + free(servername); + if (ret) + close(sock); + + return ret; +} + +int +edg_wll_gss_accept(edg_wll_GssCred cred, int sock, struct timeval *timeout, + edg_wll_GssConnection *connection, edg_wll_GssStatus* gss_code) +{ + OM_uint32 maj_stat, min_stat, min_stat2; + OM_uint32 ret_flags = 0; + gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; + gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; + gss_name_t client_name = GSS_C_NO_NAME; + gss_ctx_id_t context = GSS_C_NO_CONTEXT; + int ret; + + maj_stat = min_stat = min_stat2 = 0; + memset(connection, 0, sizeof(*connection)); + + /* GSI specific */ + ret_flags = GSS_C_GLOBUS_SSL_COMPATIBLE; + + do { + ret = recv_token(sock, &input_token.value, &input_token.length, timeout); + if (ret) + goto end; + + if (client_name != GSS_C_NO_NAME) + gss_release_name(&min_stat2, &client_name); + + maj_stat = gss_accept_sec_context(&min_stat, &context, + cred->gss_cred, &input_token, + GSS_C_NO_CHANNEL_BINDINGS, + &client_name, NULL, &output_token, + &ret_flags, NULL, NULL); + if (input_token.length > 0) { + free(input_token.value); + input_token.length = 0; + } + + if (output_token.length) { + ret = send_token(sock, output_token.value, output_token.length, timeout); + gss_release_buffer(&min_stat2, &output_token); + if (ret) + goto end; + } + } while(maj_stat & GSS_S_CONTINUE_NEEDED); + + if (GSS_ERROR(maj_stat)) { + if (context != GSS_C_NO_CONTEXT) { + gss_delete_sec_context(&min_stat2, &context, &output_token); + context = GSS_C_NO_CONTEXT; + if (output_token.length) { + send_token(sock, output_token.value, output_token.length, timeout); + gss_release_buffer(&min_stat2, &output_token); + } + } + ret = EDG_WLL_GSS_ERROR_GSS; + goto end; + } + +#if 0 + maj_stat = gss_display_name(&min_stat, client_name, &output_token, NULL); + gss_release_buffer(&min_stat2, &output_token); + if (GSS_ERROR(maj_stat)) { + /* XXX close context ??? */ + ret = EDG_WLL_GSS_ERROR_GSS; + goto end; + } +#endif + + connection->sock = sock; + connection->context = context; + ret = 0; + +end: + if (ret == EDG_WLL_GSS_ERROR_GSS && gss_code) { + gss_code->major_status = maj_stat; + gss_code->minor_status = min_stat; + } + if (client_name != GSS_C_NO_NAME) + gss_release_name(&min_stat2, &client_name); + + return ret; +} + +int +edg_wll_gss_write(edg_wll_GssConnection *connection, const void *buf, size_t bufsize, + struct timeval *timeout, edg_wll_GssStatus* gss_code) +{ + OM_uint32 maj_stat, min_stat; + gss_buffer_desc input_token; + gss_buffer_desc output_token; + int ret; + + input_token.value = (void*)buf; + input_token.length = bufsize; + + maj_stat = gss_wrap (&min_stat, connection->context, 1, GSS_C_QOP_DEFAULT, + &input_token, NULL, &output_token); + if (GSS_ERROR(maj_stat)) { + if (gss_code) { + gss_code->minor_status = min_stat; + gss_code->major_status = maj_stat; + } + + return EDG_WLL_GSS_ERROR_GSS; + } + + ret = send_token(connection->sock, output_token.value, output_token.length, + timeout); + gss_release_buffer(&min_stat, &output_token); + + return ret; +} + + +int +edg_wll_gss_read(edg_wll_GssConnection *connection, void *buf, size_t bufsize, + struct timeval *timeout, edg_wll_GssStatus* gss_code) +{ + OM_uint32 maj_stat, min_stat, min_stat2; + gss_buffer_desc input_token; + gss_buffer_desc output_token; + size_t i, len; + int ret; + + if (connection->bufsize > 0) { + len = (connection->bufsize < bufsize) ? connection->bufsize : bufsize; + memcpy(buf, connection->buffer, len); + if (connection->bufsize - len == 0) { + free(connection->buffer); + connection->buffer = NULL; + } else { + for (i = 0; i < connection->bufsize - len; i++) + connection->buffer[i] = connection->buffer[i+len]; + } + connection->bufsize -= len; + + return len; + } + + do { + ret = recv_token(connection->sock, &input_token.value, &input_token.length, + timeout); + if (ret) + return ret; + + ERR_clear_error(); + maj_stat = gss_unwrap(&min_stat, connection->context, &input_token, + &output_token, NULL, NULL); + gss_release_buffer(&min_stat2, &input_token); + if (GSS_ERROR(maj_stat)) { + if (gss_code) { + gss_code->minor_status = min_stat; + gss_code->major_status = maj_stat; + } + return EDG_WLL_GSS_ERROR_GSS; + } + } while (maj_stat == 0 && output_token.length == 0 && output_token.value == NULL); + + if (output_token.length > bufsize) { + connection->bufsize = output_token.length - bufsize; + connection->buffer = malloc(connection->bufsize); + if (connection->buffer == NULL) { + connection->bufsize = 0; + ret = EDG_WLL_GSS_ERROR_ERRNO; + goto end; + } + memcpy(connection->buffer, output_token.value + bufsize, connection->bufsize); + output_token.length = bufsize; + } + + memcpy(buf, output_token.value, output_token.length); + ret = output_token.length; + +end: + gss_release_buffer(&min_stat, &output_token); + + return ret; +} + +int +edg_wll_gss_read_full(edg_wll_GssConnection *connection, void *buf, + size_t bufsize, struct timeval *timeout, size_t *total, + edg_wll_GssStatus* gss_code) +{ + size_t len, i; + *total = 0; + + if (connection->bufsize > 0) { + len = (connection->bufsize < bufsize) ? connection->bufsize : bufsize; + memcpy(buf, connection->buffer, len); + if (connection->bufsize - len == 0) { + free(connection->buffer); + connection->buffer = NULL; + } else { + for (i = 0; i < connection->bufsize - len; i++) + connection->buffer[i] = connection->buffer[i+len]; + } + connection->bufsize -= len; + *total = len; + } + + while (*total < bufsize) { + int len; + + len = edg_wll_gss_read(connection, buf+*total, bufsize-*total, + timeout, gss_code); + if (len < 0) return len; + *total += len; + } + + return 0; +} + +int +edg_wll_gss_write_full(edg_wll_GssConnection *connection, const void *buf, + size_t bufsize, struct timeval *timeout, size_t *total, + edg_wll_GssStatus* gss_code) +{ + return edg_wll_gss_write(connection, buf, bufsize, timeout, gss_code); +} + +/* Request credential reload each 60 seconds in order to work around + * Globus bug (not reloading expired CRLs) + */ +#define GSS_CRED_WATCH_LIMIT 60 +int +edg_wll_gss_watch_creds(const char *proxy_file, time_t *last_time) +{ + struct stat pstat; + time_t now; + + now = time(NULL); + + if ( now >= (*last_time+GSS_CRED_WATCH_LIMIT) ) { + *last_time = now; + return 1; + } + + if (!proxy_file) return 0; + if (stat(proxy_file,&pstat)) return -1; + + if ( pstat.st_mtime >= *last_time ) { + *last_time = now + 1; + return 1; + } + + return 0; +} + +int +edg_wll_gss_close(edg_wll_GssConnection *con, struct timeval *timeout) +{ + OM_uint32 min_stat; + gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; + struct timeval def_timeout = { 0, 100000}; + + if (con->context != GSS_C_NO_CONTEXT) { + gss_delete_sec_context(&min_stat, (gss_ctx_id_t *)&con->context, &output_token); + +#if 0 + /* XXX: commented out till timeout handling in caller is fixed */ + + /* send the buffer (if any) to the peer. GSSAPI specs doesn't + * recommend sending it, but we want SSL compatibility */ + if (output_token.length && con->sock>=0) { + send_token(con->sock, output_token.value, output_token.length, + timeout ? timeout : &def_timeout); + } +#endif + gss_release_buffer(&min_stat, &output_token); + + /* XXX can socket be open even if context == GSS_C_NO_CONTEXT) ? */ + /* XXX ensure that edg_wll_GssConnection is created with sock set to -1 */ + if (con->sock >= 0) + close(con->sock); + } + if (con->buffer) + free(con->buffer); + memset(con, 0, sizeof(*con)); + con->context = GSS_C_NO_CONTEXT; + con->sock = -1; + return 0; +} + +int +edg_wll_gss_get_error(edg_wll_GssStatus *gss_err, const char *prefix, char **msg) +{ + OM_uint32 maj_stat, min_stat; + OM_uint32 msg_ctx = 0; + gss_buffer_desc maj_status_string = GSS_C_EMPTY_BUFFER; + gss_buffer_desc min_status_string = GSS_C_EMPTY_BUFFER; + char *str = NULL; + char *line, *tmp; + + str = strdup(prefix); + do { + maj_stat = gss_display_status(&min_stat, gss_err->major_status, + GSS_C_GSS_CODE, GSS_C_NO_OID, + &msg_ctx, &maj_status_string); + if (GSS_ERROR(maj_stat)) + break; + maj_stat = gss_display_status(&min_stat, gss_err->minor_status, + GSS_C_MECH_CODE, GSS_C_NULL_OID, + &msg_ctx, &min_status_string); + if (GSS_ERROR(maj_stat)) { + gss_release_buffer(&min_stat, &maj_status_string); + break; + } + + asprintf(&line, ": %s (%s)", (char *)maj_status_string.value, + (char *)min_status_string.value); + gss_release_buffer(&min_stat, &maj_status_string); + gss_release_buffer(&min_stat, &min_status_string); + + tmp = realloc(str, strlen(str) + strlen(line) + 1); + if (tmp == NULL) { + /* abort() ? */ + free(line); + free(str); + str = "WARNING: Not enough memory to produce error message"; + break; + } + str = tmp; + strcat(str, line); + free(line); + } while (!GSS_ERROR(maj_stat) && msg_ctx != 0); + + *msg = str; + return 0; +} + +int +edg_wll_gss_oid_equal(const gss_OID a, const gss_OID b) +{ + if (a == b) + return 1; + else { + if (a == GSS_C_NO_OID || b == GSS_C_NO_OID || a->length != b->length) + return 0; + else + return (memcmp(a->elements, b->elements, a->length) == 0); + } +} + +int +edg_wll_gss_reject(int sock) +{ + /* XXX is it possible to cut & paste edg_wll_ssl_reject() ? */ + return 0; +} + + +int +edg_wll_gss_initialize(void) +{ + int ret; + + ret = globus_module_activate(GLOBUS_GSI_GSSAPI_MODULE); + if (ret != GLOBUS_SUCCESS) { + errno = EINVAL; + ret = EDG_WLL_GSS_ERROR_ERRNO; + } + return ret; +} + +int +edg_wll_gss_release_cred(edg_wll_GssCred *cred, edg_wll_GssStatus* gss_code) +{ + OM_uint32 maj_stat, min_stat; + int ret = 0; + + if (gss_code) + gss_code->major_status = gss_code->minor_status = 0; + + if (cred == NULL || *cred == NULL) + return ret; + + if ((*cred)->gss_cred) { + maj_stat = gss_release_cred(&min_stat, (gss_cred_id_t*)&(*cred)->gss_cred); + if (GSS_ERROR(maj_stat)) { + ret = EDG_WLL_GSS_ERROR_GSS; + if (gss_code) { + gss_code->major_status = maj_stat; + gss_code->minor_status = min_stat; + } + } + } + + if ((*cred)->name) + free((*cred)->name); + + free(*cred); + *cred = NULL; + + return ret; +} + +int +edg_wll_gss_get_client_conn(edg_wll_GssConnection *connection, + edg_wll_GssPrincipal *principal, + edg_wll_GssStatus* gss_code) +{ + gss_buffer_desc token = GSS_C_EMPTY_BUFFER; + OM_uint32 maj_stat, min_stat, ctx_flags; + gss_name_t client_name = GSS_C_NO_NAME; + edg_wll_GssPrincipal p; + int ret; + + maj_stat = gss_inquire_context(&min_stat, connection->context, &client_name, + NULL, NULL, NULL, &ctx_flags, NULL, NULL); + if (GSS_ERROR(maj_stat)) + goto end; + + maj_stat = gss_display_name(&min_stat, client_name, &token, NULL); + if (GSS_ERROR(maj_stat)) + goto end; + + p = calloc(1, sizeof(*p)); + if (p == NULL) { + errno = ENOMEM; + ret = EDG_WLL_GSS_ERROR_ERRNO; + goto end; + } + + p->name = strdup(token.value); + p->flags = ctx_flags; + + *principal = p; + ret = 0; + +end: + if (GSS_ERROR(maj_stat)) { + ret = EDG_WLL_GSS_ERROR_GSS; + if (gss_code) { + gss_code->major_status = maj_stat; + gss_code->minor_status = min_stat; + } + } + + if (token.length) + gss_release_buffer(&min_stat, &token); + if (client_name != GSS_C_NO_NAME) + gss_release_name(&min_stat, &client_name); + + return ret; +} + +/* Beware, this call manipulates with environment variables and is not + thread-safe */ +static int +get_peer_cred(edg_wll_GssConnection *gss, const char *my_cert_file, + const char *my_key_file, STACK_OF(X509) **chain, + edg_wll_GssStatus* gss_code) +{ + OM_uint32 maj_stat, min_stat; + gss_buffer_desc buffer = GSS_C_EMPTY_BUFFER; + BIO *bio = NULL; + SSL_SESSION *session = NULL; + unsigned char int_buffer[4]; + long length; + int ret, index; + STACK_OF(X509) *cert_chain = NULL; + X509 *p_cert; + char *orig_cert = NULL, *orig_key = NULL; + + maj_stat = gss_export_sec_context(&min_stat, (gss_ctx_id_t *) &gss->context, + &buffer); + if (GSS_ERROR(maj_stat)) { + if (gss_code) { + gss_code->major_status = maj_stat; + gss_code->minor_status = min_stat; + } + return EDG_WLL_GSS_ERROR_GSS; + } + + /* The GSSAPI specs requires gss_export_sec_context() to destroy the + * context after exporting. So we have to resurrect the context here by + * importing from just generated buffer. gss_import_sec_context() must be + * able to read valid credential before it loads the exported context + * so we set the environment temporarily to point to the ones used by + * the server. + * */ + + orig_cert = getenv("X509_USER_CERT"); + orig_key = getenv("X509_USER_KEY"); + + if (my_cert_file) + setenv("X509_USER_CERT", my_cert_file, 1); + if (my_key_file) + setenv("X509_USER_KEY", my_key_file, 1); + + maj_stat = gss_import_sec_context(&min_stat, &buffer, + (gss_ctx_id_t *)&gss->context); + + if (orig_cert) + setenv("X509_USER_CERT", orig_cert, 1); + else + unsetenv("X509_USER_CERT"); + + if (orig_key) + setenv("X509_USER_KEY", orig_key, 1); + else + unsetenv("X509_USER_KEY"); + + if (GSS_ERROR(maj_stat)) { + if (gss_code) { + gss_code->major_status = maj_stat; + gss_code->minor_status = min_stat; + } + ret = EDG_WLL_GSS_ERROR_GSS; + goto end; + } + + bio = BIO_new(BIO_s_mem()); + if (bio == NULL) { + ret = ENOMEM; + goto end; + } + + /* Store exported context to memory, skipping the version number and and cred_usage fields */ + BIO_write(bio, buffer.value + 8 , buffer.length - 8); + + /* decode the session data in order to skip at the start of the cert chain */ + session = d2i_SSL_SESSION_bio(bio, NULL); + if (session == NULL) { + ret = EINVAL; + goto end; + } + SSL_SESSION_free(session); + + cert_chain = sk_X509_new_null(); + + BIO_read(bio, (char *) int_buffer, 4); + length = (((size_t) int_buffer[0]) << 24) & 0xffff; + length |= (((size_t) int_buffer[1]) << 16) & 0xffff; + length |= (((size_t) int_buffer[2]) << 8) & 0xffff; + length |= (((size_t) int_buffer[3]) ) & 0xffff; + + if (length == 0) { + ret = EINVAL; + goto end; + } + + for(index = 0; index < length; index++) { + p_cert = d2i_X509_bio(bio, NULL); + if (p_cert == NULL) { + ret = EINVAL; + sk_X509_pop_free(cert_chain, X509_free); + goto end; + } + + sk_X509_push(cert_chain, p_cert); + } + + *chain = cert_chain; + ret = 0; + +end: + gss_release_buffer(&min_stat, &buffer); + + return ret; +} + +int +edg_wll_gss_get_client_pem(edg_wll_GssConnection *connection, + const char *my_cert_file, const char *my_key_file, + char **pem_string) +{ + char *tmp = NULL; + STACK_OF(X509) *chain = NULL; + BIO *bio = NULL; + int ret, i; + size_t total_len, l; + + ret = get_peer_cred(connection, my_cert_file, my_key_file, &chain, NULL); + if (ret) + return ret; + + bio = BIO_new(BIO_s_mem()); + if (bio == NULL) { + ret = ENOMEM; + goto end; + } + + for (i = 0; i < sk_X509_num(chain); i++) { + ret = PEM_write_bio_X509(bio, sk_X509_value(chain, i)); + if (ret <= 0) { + ret = EINVAL; + goto end; + } + } + + total_len = BIO_pending(bio); + if (total_len <= 0) { + ret = EINVAL; + goto end; + } + + tmp = malloc(total_len + 1); + if (tmp == NULL) { + ret = ENOMEM; + goto end; + } + + l = 0; + while (l < total_len) { + ret = BIO_read(bio, tmp+l, total_len-l); + if (ret <= 0) { + ret = EINVAL; + goto end; + } + l += ret; + } + + tmp[total_len] = '\0'; + *pem_string = tmp; + tmp = NULL; + + ret = 0; + +end: + sk_X509_pop_free(chain, X509_free); + if (bio) + BIO_free(bio); + if (tmp) + free(tmp); + + return ret; +} + +void +edg_wll_gss_free_princ(edg_wll_GssPrincipal principal) +{ + if (principal == NULL) + return; + + if (principal->name) + free(principal->name); + + free(principal); +} + +int +edg_wll_gss_gethostname(char *name, int len) +{ + int ret; + + ret = globus_module_activate(GLOBUS_COMMON_MODULE); + if (ret != GLOBUS_SUCCESS) { + ret = gethostname(name, len); + return ret; + } + ret = globus_libc_gethostname(name, len); + globus_module_deactivate(GLOBUS_COMMON_MODULE); + + return ret; +} + +char * +edg_wll_gss_normalize_subj(char *in, int replace_in) +{ + char *new, *ptr; + size_t len; + + if (in == NULL) return NULL; + if (replace_in) + new = in; + else + new = strdup(in); + + while ((ptr = strstr(new, "/emailAddress="))) { + memcpy(ptr, "/Email=",7); + memmove(ptr+7, ptr+14, strlen(ptr+14)+1); + } + + len = strlen(new); + while (len > 9 && !strcmp(new+len-9, "/CN=proxy")) { + *(new+len-9) = '\0'; + len -= 9; + } + + return new; +} + +int +edg_wll_gss_equal_subj(const char *a, const char *b) +{ + char *an,*bn; + int res; + + an = edg_wll_gss_normalize_subj((char*)a, 0); + bn = edg_wll_gss_normalize_subj((char*)b, 0); + + if (!an || !bn) + res = 0; + else + res = !strcmp(an,bn); + + free(an); free(bn); + return res; +} + +int +edg_wll_gss_unread(edg_wll_GssConnection *con, void *data, size_t len) +{ + char *tmp; + + if (len == 0) + return 0; + + tmp = malloc(len + con->bufsize); + if (tmp == NULL) + return ENOMEM; + + memcpy(tmp, data, len); + if (con->bufsize > 0) + memcpy(tmp + len, con->buffer, con->bufsize); + + free(con->buffer); + con->buffer = tmp; + con->bufsize += len; + + return 0; +} diff --git a/org.glite.lbjp-common.gss/test/test_gss.cpp b/org.glite.lbjp-common.gss/test/test_gss.cpp new file mode 100644 index 0000000..5eafe78 --- /dev/null +++ b/org.glite.lbjp-common.gss/test/test_gss.cpp @@ -0,0 +1,237 @@ +/* +Copyright (c) Members of the EGEE Collaboration. 2004-2010. +See http://www.eu-egee.org/partners for details on the copyright holders. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "glite_gss.h" + +class GSSTest: public CppUnit::TestFixture +{ + CPPUNIT_TEST_SUITE(GSSTest); + CPPUNIT_TEST(echo); + CPPUNIT_TEST(echo); + CPPUNIT_TEST(bigecho); + CPPUNIT_TEST(errorTest); + CPPUNIT_TEST_SUITE_END(); + +public: + void echo(); + void bigecho(); + void errorTest(); + + void setUp(); + void tearDown(); + +private: + edg_wll_GssCred my_cred; + int sock, port; + struct timeval timeout; + + void replier(); +}; + + +void GSSTest::replier() { + edg_wll_GssConnection conn; + edg_wll_GssStatus stat; + struct sockaddr_storage a; + socklen_t alen = sizeof(a); + int s, len; + char buf[8*BUFSIZ]; + + std::cerr << "replier " << getpid() << std::endl; + + if ( (s = accept(sock, (struct sockaddr *) &a, &alen)) < 0 ) exit(1); + + if ( edg_wll_gss_accept(my_cred, s, &timeout, &conn, &stat) ) exit(1); + + while ( (len = edg_wll_gss_read(&conn, buf, sizeof(buf), &timeout, &stat)) >= 0 ) { + if ( edg_wll_gss_write(&conn, buf, len, &timeout, &stat) ) exit(1); + } + + edg_wll_gss_close(&conn, &timeout); + + exit(0); +} + + +void GSSTest::setUp(void) { + pid_t pid; + edg_wll_GssStatus stat; + struct sockaddr_storage a; + socklen_t alen = sizeof(a); + char * cred_file = NULL; + char * key_file = NULL; + char * to = getenv("GSS_TEST_TIMEOUT"); + struct addrinfo *ai; + struct addrinfo hints; + char servname[16]; + int ret; + + + timeout.tv_sec = to ? atoi(to) : 10 ; + timeout.tv_usec = 0; + my_cred = NULL; + + key_file = cred_file = getenv("X509_USER_PROXY"); + CPPUNIT_ASSERT_MESSAGE("credential file", cred_file); + + if (edg_wll_gss_acquire_cred_gsi(cred_file, key_file, &my_cred, &stat)) + CPPUNIT_ASSERT_MESSAGE("gss_acquire_cred", 0); + + memset (&hints, '\0', sizeof (hints)); + hints.ai_flags = AI_NUMERICSERV | AI_PASSIVE | AI_ADDRCONFIG; + hints.ai_socktype = SOCK_STREAM; + + snprintf(servname, sizeof servname, "%d", port); + ret = getaddrinfo (NULL, servname, &hints, &ai); + CPPUNIT_ASSERT_MESSAGE("getaddrinfo()", ret == 0 && ai != NULL); + + sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + CPPUNIT_ASSERT_MESSAGE("socket()", sock >= 0); + + ret = bind(sock, ai->ai_addr, ai->ai_addrlen); + CPPUNIT_ASSERT_MESSAGE("bind()", ret == 0); + + ret = listen(sock, 1); + CPPUNIT_ASSERT_MESSAGE("listen()", ret == 0); + + getsockname(sock,(struct sockaddr *) &a,&alen); + ret = getnameinfo ((struct sockaddr *) &a, alen, + NULL, 0, servname, sizeof(servname), NI_NUMERICSERV); + CPPUNIT_ASSERT_MESSAGE("getnameinfo()", ret == 0); + + port = atoi(servname); + + if ( !(pid = fork()) ) replier(); + else close(sock); +} + + +void GSSTest::tearDown(void) { + edg_wll_gss_release_cred(&my_cred, NULL); +} + + +void GSSTest::echo() +{ + edg_wll_GssConnection conn; + edg_wll_GssStatus stat; + size_t total; + int err; + char buf[] = "f843fejwfanczn nc4*&686%$$&^(*)*#$@WSH"; + char buf2[100]; + + std::cerr << "echo " << getpid() << std::endl; + + err = edg_wll_gss_connect(my_cred, "localhost", port, &timeout, &conn, &stat); + CPPUNIT_ASSERT_MESSAGE("edg_wll_gss_connect()", !err); + + err = edg_wll_gss_write(&conn, buf, strlen(buf)+1, &timeout, &stat); + CPPUNIT_ASSERT_MESSAGE("edg_wll_gss_write()", !err); + + err = edg_wll_gss_read_full(&conn, buf2, strlen(buf)+1, &timeout, &total, &stat); + CPPUNIT_ASSERT_MESSAGE("edg_wll_gss_read_full()", !err); + + CPPUNIT_ASSERT(strlen(buf)+1 == total && !strcmp(buf,buf2) ); + + edg_wll_gss_close(&conn, &timeout); + +} + +void GSSTest::bigecho() +{ + edg_wll_GssConnection conn; + edg_wll_GssStatus stat; + size_t total; + int err; + char buf[7*BUFSIZ]; + char buf2[7*BUFSIZ]; + + std::cerr << "bigecho " << getpid() << std::endl; + + err = edg_wll_gss_connect(my_cred, "localhost", port, &timeout, &conn, &stat); + CPPUNIT_ASSERT_MESSAGE("edg_wll_gss_connect()", !err); + + err = edg_wll_gss_write(&conn, buf, sizeof buf, &timeout, &stat); + CPPUNIT_ASSERT_MESSAGE("edg_wll_gss_write()", !err); + + err = edg_wll_gss_read_full(&conn, buf2, sizeof buf2, &timeout, &total, &stat); + CPPUNIT_ASSERT_MESSAGE("edg_wll_gss_read_full()", !err); + + CPPUNIT_ASSERT(sizeof buf == total && !memcmp(buf,buf2,sizeof buf) ); + + edg_wll_gss_close(&conn, &timeout); + +} + + +void GSSTest::errorTest() +{ + edg_wll_GssConnection conn; + edg_wll_GssStatus stat; + int err; + char * msg = NULL; + + + err = edg_wll_gss_connect(my_cred, "xxx.example.net", port, &timeout, &conn, &stat); + if (err) edg_wll_gss_get_error(&stat, "gss_connect()", &msg); + CPPUNIT_ASSERT_MESSAGE("edg_wll_gss_get_error()", msg); +} + + +CPPUNIT_TEST_SUITE_REGISTRATION( GSSTest ); + +int main (int ac,const char *av[]) +{ + assert(ac == 2); + std::ofstream xml(av[1]); + + CppUnit::Test *suite = CppUnit::TestFactoryRegistry::getRegistry().makeTest(); + CppUnit::TestRunner runner; + + CppUnit::TestResult controller; + CppUnit::TestResultCollector result; + controller.addListener( &result ); + + runner.addTest(suite); + runner.run(controller); + + + CppUnit::XmlOutputter xout( &result, xml ); + CppUnit::CompilerOutputter tout( &result, std::cout); + xout.write(); + tout.write(); + + return result.wasSuccessful() ? 0 : 1 ; +} -- 1.8.2.3